From 51a0f6cd5130b804b06b774d520d39cacc73a065 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 16 Nov 2020 14:07:56 +0800 Subject: [PATCH 01/64] use js typedarray constructor to create view of underlying buffer --- rosidl_gen/deallocator.js | 6 ------ rosidl_gen/templates/message.dot | 3 +-- src/rcl_bindings.cpp | 25 ------------------------- 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/rosidl_gen/deallocator.js b/rosidl_gen/deallocator.js index 6e7cf99c..83dce427 100644 --- a/rosidl_gen/deallocator.js +++ b/rosidl_gen/deallocator.js @@ -17,12 +17,6 @@ const rclnodejs = require('bindings')('rclnodejs'); let deallocator = { - delayFreeStructMember(refObj, type, name) { - return rclnodejs.createArrayBufferCleaner( - refObj.ref(), - type.fields[name].offset - ); - }, freeStructMember(refObj, type, name) { rclnodejs.freeMemeoryAtOffset(refObj.ref(), type.fields[name].offset); }, diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index a6943adf..f4e910f2 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -750,8 +750,7 @@ class {{=arrayWrapper}} { {{? usePlainTypedArray}} const byteLen = refObject.size * ref.types.{{=currentTypedArrayElementType}}.size; // An ArrayBuffer object that doesn't hold the ownership of the address - const arrayBuffer = rclnodejs.createArrayBufferFromAddress(refObject.data, byteLen); - this._wrappers = new {{=currentTypedArray}}(arrayBuffer); + this._wrappers = new {{=currentTypedArray}}(refObject.data.buffer, refObject.data.byteOffset, refObject.size); {{?? true}} let refObjectArray = this._refObject.data; refObjectArray.length = this._refObject.size; diff --git a/src/rcl_bindings.cpp b/src/rcl_bindings.cpp index 66e8d12c..bd2ccbdc 100644 --- a/src/rcl_bindings.cpp +++ b/src/rcl_bindings.cpp @@ -1318,29 +1318,6 @@ NAN_METHOD(FreeMemeoryAtOffset) { info.GetReturnValue().Set(Nan::Undefined()); } -NAN_METHOD(CreateArrayBufferFromAddress) { - char* addr = GetBufAddr(info[0]); - int32_t length = Nan::To(info[1]).FromJust(); - - // We will create an ArrayBuffer with mode of - // ArrayBufferCreationMode::kInternalized and copy data starting from |addr|, - // thus the memory block will be collected by the garbage collector. - v8::Local array_buffer = - v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), addr, length, - v8::ArrayBufferCreationMode::kInternalized); - - info.GetReturnValue().Set(array_buffer); -} - -NAN_METHOD(CreateArrayBufferCleaner) { - auto address = GetBufAddr(info[0]); - int32_t offset = Nan::To(info[1]).FromJust(); - - char* target = *reinterpret_cast(address + offset); - info.GetReturnValue().Set( - RclHandle::NewInstance(target, nullptr, [] { return RCL_RET_OK; })); -} - NAN_METHOD(setLoggerLevel) { v8::Local currentContent = Nan::GetCurrentContext(); std::string name( @@ -1798,8 +1775,6 @@ std::vector binding_methods = { {"getNamespace", GetNamespace}, {"initString", InitString}, {"freeMemeoryAtOffset", FreeMemeoryAtOffset}, - {"createArrayBufferFromAddress", CreateArrayBufferFromAddress}, - {"createArrayBufferCleaner", CreateArrayBufferCleaner}, {"setLoggerLevel", setLoggerLevel}, {"getLoggerEffectiveLevel", GetLoggerEffectiveLevel}, {"getNodeLoggerName", GetNodeLoggerName}, From f39edb26eb67557a763da894a33f8887d149e561 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 16 Nov 2020 16:33:58 +0800 Subject: [PATCH 02/64] fix leak in RclTakeRequest --- src/rcl_bindings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rcl_bindings.cpp b/src/rcl_bindings.cpp index bd2ccbdc..5105c9b1 100644 --- a/src/rcl_bindings.cpp +++ b/src/rcl_bindings.cpp @@ -906,6 +906,7 @@ NAN_METHOD(RclTakeRequest) { return; } + free(header); info.GetReturnValue().Set(Nan::Undefined()); } From a287e2e31fd0b78ac7ea11010dbc549fd133ae15 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 17 Nov 2020 17:54:46 +0800 Subject: [PATCH 03/64] wip --- .prettierrc.yml | 4 + binding.gyp | 139 +- package-lock.json | 4607 +++++++++++++++++ rosidl_gen/idl_generator.js | 167 +- rosidl_gen/index.js | 43 +- rosidl_gen/templates/cppDefinitions.dot | 111 + rosidl_gen/templates/cppDefinitionsHeader.dot | 35 + rosidl_gen/templates/message.dot | 3 +- rosidl_gen/templates/typesupportGypi.dot | 12 + scripts/generate_messages.js | 2 +- src/rcl_bindings.cpp | 25 + src/type_conversion.hpp | 67 + 12 files changed, 5144 insertions(+), 71 deletions(-) create mode 100644 .prettierrc.yml create mode 100644 package-lock.json create mode 100644 rosidl_gen/templates/cppDefinitions.dot create mode 100644 rosidl_gen/templates/cppDefinitionsHeader.dot create mode 100644 rosidl_gen/templates/typesupportGypi.dot create mode 100644 src/type_conversion.hpp diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..0b9ecd4e --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,4 @@ +{ + singleQuote: true, + trailingComma: es5, +} diff --git a/binding.gyp b/binding.gyp index 54f69ec7..fe69e337 100644 --- a/binding.gyp +++ b/binding.gyp @@ -10,6 +10,82 @@ 'variables': { 'ros_version': '=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-from-current-process-h": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-from-current-process-h/-/get-symbol-from-current-process-h-1.0.2.tgz", + "integrity": "sha512-syloC6fsCt62ELLrr1VKBM1ggOpMdetX9hTrdW77UQdcApPHLmf7CI7OKcN1c9kYuNxKcDe4iJ4FY9sX3aw2xw==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "int64-napi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/int64-napi/-/int64-napi-1.0.1.tgz", + "integrity": "sha512-UPprIixcZdhdLobpKgHm6/HJD9VIR53JE5Fx93nJzgnX10hCxUd8nzOukxL2WDmjT2SWfz/VzDvk6qfPBLnEVg==", + "requires": { + "bindings": "^1.3.0" + } + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-close": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/is-close/-/is-close-1.3.3.tgz", + "integrity": "sha512-Q8pmIuDS2BUAj9NElFDxKNv11JXWqXNVa5+i3kjWmT0r2SVxVkXmBCexBuooPS4r59C5F3STMi5thXKP56/FIg==" + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "iterate-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", + "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-extend": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "lint-staged": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.0.tgz", + "integrity": "sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.0.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.1.1", + "dedent": "^0.7.0", + "enquirer": "^2.3.6", + "execa": "^4.0.3", + "listr2": "^2.6.0", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "listr2": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.2.tgz", + "integrity": "sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "figures": "^3.2.0", + "indent-string": "^4.0.0", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rxjs": "^6.6.2", + "through": "^2.3.8" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mocha": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", + "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.4.2", + "debug": "4.1.1", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.2", + "object.assign": "4.1.0", + "promise.allsettled": "1.0.2", + "serialize-javascript": "4.0.0", + "strip-json-comments": "3.0.1", + "supports-color": "7.1.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.0", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nise": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", + "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-gyp-build": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", + "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "npm-registry-client": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.6.0.tgz", + "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", + "dev": true, + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parsimmon": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.16.0.tgz", + "integrity": "sha512-tekGDz2Lny27SQ/5DzJdIK0lqsWwZ667SCLFIDCxaZM7VNgQjyKLbaL7FYPKpbjdxNAXFV/mSxkq5D2fnkW4pA==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise.allsettled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", + "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.1", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "iterate-value": "^1.0.0" + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "ref-array-di": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ref-array-di/-/ref-array-di-1.2.2.tgz", + "integrity": "sha512-jhCmhqWa7kvCVrWhR/d7RemkppqPUdxEil1CtTtm7FkZV8LcHHCK3Or9GinUiFP5WY3k0djUkMvhBhx49Jb2iA==", + "requires": { + "array-index": "^1.0.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "ref-napi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-3.0.1.tgz", + "integrity": "sha512-W3rcb0E+tlO9u9ySFnX5vifInwwPGToOfFgTZUHJBNiOBsW0NNvgHz2zJN7ctABo/2yIlgdPQUvuqqfORIF4LA==", + "requires": { + "debug": "^4.1.1", + "get-symbol-from-current-process-h": "^1.0.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.1" + } + }, + "ref-struct-di": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ref-struct-di/-/ref-struct-di-1.1.1.tgz", + "integrity": "sha512-2Xyn/0Qgz89VT+++WP0sTosdm9oeowLP23wRJYhG4BFdMUrLj3jhwHZNEytYNYgtPKLNTP3KJX4HEgBvM1/Y2g==", + "requires": { + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "sinon": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.3.tgz", + "integrity": "sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.1.0", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tslint": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz", + "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "dev": true + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "walk": { + "version": "2.3.14", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", + "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", + "requires": { + "foreachasync": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workerpool": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", + "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", + "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", + "flat": "^4.1.0", + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 0bb7abab..a588e00f 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -15,17 +15,78 @@ 'use strict'; const dot = require('dot'); +const fs = require('fs').promises; const fse = require('fs-extra'); const path = require('path'); const parser = require('../rosidl_parser/rosidl_parser.js'); const actionMsgs = require('./action_msgs.js'); +class RosIdlDb { + constructor(pkgs) { + this.specDb = {}; + this.messageInfoIndex = {}; + for (let pkg of pkgs.values()) { + pkg.messages.forEach((messageInfo) => { + this.messageInfoIndex[ + `${messageInfo.pkgName}__${messageInfo.interfaceName}` + ] = messageInfo; + }); + } + } + + getMessageInfoFromType(type) { + return this.messageInfoIndex[`${type.pkgName}__${type.type}`]; + } + + _messageInfoHash(messageInfo) { + return `${messageInfo.pkgName}__${messageInfo.interfaceName}`; + } + + async getMessageSpec(messageInfo) { + let spec = this.specDb[this._messageInfoHash(messageInfo)]; + if (spec) { + return spec; + } + const promise = new Promise(async (res) => { + const spec = await parser.parseMessageFile( + messageInfo.pkgName, + messageInfo.filePath + ); + this.specDb[this._messageInfoHash(messageInfo)] = spec; + res(spec); + }); + this.specDb[this._messageInfoHash(messageInfo)] = promise; + return promise; + } + + // _getDependentPackagesImpl(pkg) + + // getDependentPackages(pkg) { + // pkg.messages.forEach((messageInfo) => { + + // }) + // } +} + dot.templateSettings.strip = false; dot.log = process.env.RCLNODEJS_LOG_VERBOSE || false; const dots = dot.process({ path: path.join(__dirname, '../rosidl_gen/templates'), }); +function pascalToSnakeCase(s) { + return s + .split(/(?=[A-Z])/) + .join('_') + .toLowerCase(); +} + +function getRosHeaderField(messageInfo) { + return `${messageInfo.pkgName}/${messageInfo.subFolder}/${pascalToSnakeCase( + messageInfo.interfaceName + )}.h`; +} + function removeEmptyLines(str) { return str.replace(/^\s*\n/gm, ''); } @@ -50,11 +111,8 @@ function generateServiceJSStruct(serviceInfo, dir) { return writeGeneratedCode(dir, fileName, generatedCode); } -async function generateMessageJSStruct(messageInfo, dir) { - const spec = await parser.parseMessageFile( - messageInfo.pkgName, - messageInfo.filePath - ); +async function generateMessageJSStruct(messageInfo, dir, rosIdlDb) { + const spec = await rosIdlDb.getMessageSpec(messageInfo); await generateMessageJSStructFromSpec(messageInfo, dir, spec); } @@ -78,6 +136,86 @@ function generateMessageJSStructFromSpec(messageInfo, dir, spec) { return writeGeneratedCode(dir, fileName, generatedCode); } +function getCppSourcePath(pkgName) { + return path.join('src', 'generated', pkgName, 'definitions.cpp'); +} + +function getCppHeaderPath(pkgName) { + return path.join('src', 'generated', pkgName, 'definitions.hpp'); +} + +function getJsType(rosType) { + if (rosType.isArray) { + return 'object'; + } + if (rosType.type === 'int64' || rosType.type === 'uint64') { + return 'bigint'; + } else if ( + rosType.type.startsWith('int') || + rosType.type.startsWith('uint') || + rosType.type.startsWith('float') || + rosType.type === 'double' || + rosType.type === 'byte' || + rosType.type === 'char' + ) { + return 'number'; + } else if (rosType.type === 'string') { + return 'string'; + } else if (rosType.type === 'bool') { + return 'boolean'; + } + return 'object'; +} + +// All messages are combined in one cpp file to improve compile time. +async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { + // console.log(messageInfo); + // console.log(spec); + // console.log(spec.fields); + + const getStructType = (messageInfo) => { + return `${messageInfo.pkgName}__${messageInfo.subFolder}__${messageInfo.interfaceName}`; + }; + + const getStructTypeFromRosType = (type) => { + const messageInfo = rosIdlDb.getMessageInfoFromType(type); + return getStructType(messageInfo); + }; + + const messages = []; + + // this is slower but doing it sequentially maintains ordering + for (let messageInfo of pkgInfo.messages) { + messages.push({ + info: messageInfo, + spec: await rosIdlDb.getMessageSpec(messageInfo), + structType: getStructType(messageInfo), + }); + } + + const source = removeEmptyLines( + dots.cppDefinitions({ + messages, + rosIdlDb, + getRosHeaderField, + getStructTypeFromRosType, + getJsType, + }) + ); + + const header = removeEmptyLines( + dots.cppDefinitionsHeader({ + messages, + rosIdlDb, + getRosHeaderField, + getStructTypeFromRosType, + }) + ); + + await fs.writeFile(getCppSourcePath(pkgName), source); + await fs.writeFile(getCppHeaderPath(pkgName), header); +} + async function generateActionJSStruct(actionInfo, dir) { const spec = await parser.parseActionFile( actionInfo.pkgName, @@ -230,10 +368,10 @@ async function generateActionJSStruct(actionInfo, dir) { ]); } -async function generateJSStructFromIDL(pkg, dir) { +async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { await Promise.all([ ...pkg.messages.map((messageInfo) => - generateMessageJSStruct(messageInfo, dir) + generateMessageJSStruct(messageInfo, dir, rosIdlDb) ), ...pkg.services.map((serviceInfo) => generateServiceJSStruct(serviceInfo, dir) @@ -242,4 +380,17 @@ async function generateJSStructFromIDL(pkg, dir) { ]); } -module.exports = generateJSStructFromIDL; +async function generateTypesupportGypi(pkgs) { + const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); + await fs.writeFile( + path.join('src', 'generated', 'typesupport.gypi'), + rendered + ); +} + +module.exports = { + RosIdlDb, + generateJSStructFromIDL, + generateCppDefinitions, + generateTypesupportGypi, +}; diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index bab0b6cb..54b41667 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -15,7 +15,12 @@ 'use strict'; const fse = require('fs-extra'); -const generateJSStructFromIDL = require('./idl_generator.js'); +const { + RosIdlDb, + generateJSStructFromIDL, + generateCppDefinitions, + generateTypesupportGypi, +} = require('./idl_generator.js'); const packages = require('./packages.js'); const path = require('path'); @@ -25,11 +30,43 @@ const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split( ); async function generateInPath(path) { - const pkgs = await packages.findPackagesInDirectory(path); + const results = []; + // const pkgs = await packages.findPackagesInDirectory(path); + const pkgs = new Map(); + pkgs.set('test_msgs', { + pkgName: 'test_msgs', + messages: [ + { + interfaceName: 'Nested', + subFolder: 'msg', + filePath: '/opt/ros/foxy/share/test_msgs/msg/Nested.msg', + }, + { + interfaceName: 'BasicTypes', + subFolder: 'msg', + filePath: '/opt/ros/foxy/share/test_msgs/msg/BasicTypes.msg', + }, + ], + services: [], + actions: [], + }); + + const rosIdlDb = new RosIdlDb(pkgs); + const pkgsInfo = Array.from(pkgs.values()); + const pkgsEntries = Array.from(pkgs.entries()); + + await Promise.all( + pkgsInfo.map((pkgInfo) => + generateJSStructFromIDL(pkgInfo, generatedRoot, rosIdlDb) + ) + ); await Promise.all( - pkgsInfo.map((pkgInfo) => generateJSStructFromIDL(pkgInfo, generatedRoot)) + pkgsEntries.map(([pkgName, pkgInfo]) => + generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) + ) ); + await generateTypesupportGypi(pkgsInfo); } async function generateAll(forcedGenerating) { diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot new file mode 100644 index 00000000..2ce7948e --- /dev/null +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -0,0 +1,111 @@ +// This file is automatically generated by rclnodejs +// +// *** DO NOT EDIT directly +// + +#include "definitions.hpp" +#include "../../type_conversion.hpp" + +{{~ it.messages : message }} +#include <{{=it.getRosHeaderField(message.info)}}> +{{~}} + +namespace rclnodejs { + +{{~ it.messages : message }} +NAN_MODULE_INIT(rclnodejs__{{=message.structType}}::Init) { + auto obj = Nan::New(); + obj->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); + obj->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); + obj->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); + Nan::Set(target, Nan::New("{{=message.structType}}").ToLocalChecked(), obj); +} + +void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsObj, {{=message.structType}}* msg) { +{{~ message.spec.fields : field}} + auto {{=field.name}} = jsObj->Get(Nan::New("{{=field.name}}").ToLocalChecked()); +{{ + const jsType = it.getJsType(field.type); +}} +{{? jsType === 'number'}} + if (!{{=field.name}}->IsNumber()) { + throw new std::runtime_error("expected {{=field.name}} to be number"); + } +{{?? jsType === 'string'}} + if (!{{=field.name}}->IsString()) { + throw new std::runtime_error("expected {{=field.name}} to be string"); + } +{{?? jsType === 'boolean'}} + if (!{{=field.name}}->IsBoolean()) { + throw new std::runtime_error("expected {{=field.name}} to be boolean"); + } +{{?? jsType === 'bigint'}} + if (!{{=field.name}}->IsBigInt()) { + throw new std::runtime_error("expected {{=field.name}} to be bigint"); + } +{{??}} + if (!{{=field.name}}->IsObject()) { + throw new std::runtime_error("expected {{=field.name}} to be {{=field.type.type}} object"); + } +{{?}} +{{? field.type.isPrimitiveType && !field.type.isArray}} + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>({{=field.name}}); +{{?? !field.type.isPrimitiveType}} + rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::WriteMessage(Nan::To({{=field.name}}).ToLocalChecked(), &msg->{{=field.name}}); +{{??}} + // TODO: handle array types +{{?}} +{{~}} +} + +v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=message.structType}}* msg) { + auto jsObj = Nan::New(); +{{~ message.spec.fields : field}} +{{? !field.type.isArray}} +{{? field.type.isPrimitiveType}} + jsObj->Set(Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); +{{??}} + jsObj->Set(Nan::New("{{=field.name}}").ToLocalChecked(), rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::MakeJsObject(&msg->{{=field.name}})); +{{?}} +{{??}} + // TODO: handle array +{{?}} +{{~}} + return jsObj; +} + +NAN_METHOD(rclnodejs__{{=message.structType}}::Create) { + auto* data = {{=message.structType}}__create(); + auto buffer = Nan::NewBuffer(reinterpret_cast(data), sizeof(*data), [](auto* data, auto) { + {{=message.structType}}__destroy(reinterpret_cast<{{=message.structType}}*>(data)); + }, nullptr).ToLocalChecked(); + info.GetReturnValue().Set(buffer); +} + +NAN_METHOD(rclnodejs__{{=message.structType}}::FromJsObject) { + auto jsObj = Nan::To(info[0]).ToLocalChecked(); + auto* msg = {{=message.structType}}__create(); + + try { + rclnodejs__{{=message.structType}}::WriteMessage(jsObj, msg); + } catch (const std::runtime_error& e) { + Nan::ThrowError(Nan::New(e.what()).ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; + } + + auto buffer = Nan::NewBuffer(reinterpret_cast(msg), sizeof(*msg), [](auto* msg, auto) { + {{=message.structType}}__destroy(reinterpret_cast<{{=message.structType}}*>(msg)); + }, nullptr).ToLocalChecked(); + info.GetReturnValue().Set(buffer); +} + +NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { + auto* buffer = node::Buffer::Data(info[0]); + auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer); + info.GetReturnValue().Set(rclnodejs__{{=message.structType}}::MakeJsObject(msg)); +} + +{{~}} + +} // namespace rclnodejs diff --git a/rosidl_gen/templates/cppDefinitionsHeader.dot b/rosidl_gen/templates/cppDefinitionsHeader.dot new file mode 100644 index 00000000..2e6ec676 --- /dev/null +++ b/rosidl_gen/templates/cppDefinitionsHeader.dot @@ -0,0 +1,35 @@ +// This file is automatically generated by rclnodejs +// +// *** DO NOT EDIT directly +// + +#include + +{{~ it.messages : message}} +struct {{=message.structType}}; +{{~}} + +namespace rclnodejs { + +{{~ it.messages : message }} +class rclnodejs__{{=message.structType}} { + public: + static NAN_MODULE_INIT(Init); + + static void WriteMessage(v8::Local jsObj, {{=message.structType}}* msg); + + /** + * Must be called within a v8 scope + */ + static v8::Local MakeJsObject({{=message.structType}}* msg); + + private: + static NAN_METHOD(Create); + + static NAN_METHOD(FromJsObject); + + static NAN_METHOD(ToJsObject); +}; +{{~}} + +} // namespace rclnodejs diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index f4e910f2..a6943adf 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -750,7 +750,8 @@ class {{=arrayWrapper}} { {{? usePlainTypedArray}} const byteLen = refObject.size * ref.types.{{=currentTypedArrayElementType}}.size; // An ArrayBuffer object that doesn't hold the ownership of the address - this._wrappers = new {{=currentTypedArray}}(refObject.data.buffer, refObject.data.byteOffset, refObject.size); + const arrayBuffer = rclnodejs.createArrayBufferFromAddress(refObject.data, byteLen); + this._wrappers = new {{=currentTypedArray}}(arrayBuffer); {{?? true}} let refObjectArray = this._refObject.data; refObjectArray.length = this._refObject.size; diff --git a/rosidl_gen/templates/typesupportGypi.dot b/rosidl_gen/templates/typesupportGypi.dot new file mode 100644 index 00000000..37bd3efa --- /dev/null +++ b/rosidl_gen/templates/typesupportGypi.dot @@ -0,0 +1,12 @@ +{ + 'targets': [ +{{~ it.pkgs : pkg}} + { + 'target_name': '{{=pkg.pkgName}}', + 'sources': [ + '{{=pkg.pkgName}}/definitions.cpp', + ], + }, +{{~}} + ], +} diff --git a/scripts/generate_messages.js b/scripts/generate_messages.js index 3e1e7e4a..45756336 100644 --- a/scripts/generate_messages.js +++ b/scripts/generate_messages.js @@ -23,7 +23,7 @@ async function main() { try { await generator.generateAll(true); - await tsdGenerator.generateAll(); // create interfaces.d.ts + // await tsdGenerator.generateAll(); // create interfaces.d.ts console.log('Generation complete.'); } catch (e) { console.log(`Caught error: ${e}`); diff --git a/src/rcl_bindings.cpp b/src/rcl_bindings.cpp index 5a02b722..3cd75926 100644 --- a/src/rcl_bindings.cpp +++ b/src/rcl_bindings.cpp @@ -1275,6 +1275,29 @@ NAN_METHOD(FreeMemeoryAtOffset) { info.GetReturnValue().Set(Nan::Undefined()); } +NAN_METHOD(CreateArrayBufferFromAddress) { + char* addr = GetBufAddr(info[0]); + int32_t length = Nan::To(info[1]).FromJust(); + + // We will create an ArrayBuffer with mode of + // ArrayBufferCreationMode::kInternalized and copy data starting from |addr|, + // thus the memory block will be collected by the garbage collector. + v8::Local array_buffer = + v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), addr, length, + v8::ArrayBufferCreationMode::kInternalized); + + info.GetReturnValue().Set(array_buffer); +} + +NAN_METHOD(CreateArrayBufferCleaner) { + auto address = GetBufAddr(info[0]); + int32_t offset = Nan::To(info[1]).FromJust(); + + char* target = *reinterpret_cast(address + offset); + info.GetReturnValue().Set( + RclHandle::NewInstance(target, nullptr, [] { return RCL_RET_OK; })); +} + NAN_METHOD(setLoggerLevel) { v8::Local currentContent = Nan::GetCurrentContext(); std::string name( @@ -1732,6 +1755,8 @@ std::vector binding_methods = { {"getNamespace", GetNamespace}, {"initString", InitString}, {"freeMemeoryAtOffset", FreeMemeoryAtOffset}, + {"createArrayBufferFromAddress", CreateArrayBufferFromAddress}, + {"createArrayBufferCleaner", CreateArrayBufferCleaner}, {"setLoggerLevel", setLoggerLevel}, {"getLoggerEffectiveLevel", GetLoggerEffectiveLevel}, {"getNodeLoggerName", GetNodeLoggerName}, diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp new file mode 100644 index 00000000..c55d8495 --- /dev/null +++ b/src/type_conversion.hpp @@ -0,0 +1,67 @@ +#ifndef RCLNODEJS_TYPE_CONVERSION_HPP_ +#define RCLNODEJS_TYPE_CONVERSION_HPP_ + +#include + +namespace rclnodejs { + +template +inline T ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template <> +inline int8_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template <> +inline uint8_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template <> +inline int16_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template <> +inline uint16_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template <> +inline int64_t ToNativeChecked(v8::Local val) { + return val->ToBigInt(Nan::GetCurrentContext()).ToLocalChecked()->Int64Value(); +} + +template <> +inline uint64_t ToNativeChecked(v8::Local val) { + return val->ToBigInt(Nan::GetCurrentContext()) + .ToLocalChecked() + ->Uint64Value(); +} + +template <> +inline float ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); +} + +template +inline v8::Local ToJsChecked(T val) { + return Nan::New(val); +} + +template <> +inline v8::Local ToJsChecked(int64_t val) { + return v8::BigInt::New(Nan::GetCurrentContext()->GetIsolate(), val); +} + +template <> +inline v8::Local ToJsChecked(uint64_t val) { + return v8::BigInt::NewFromUnsigned(Nan::GetCurrentContext()->GetIsolate(), val); +} + +} // namespace rclnodejs + +#endif From 0c56585b315525b6e3706c118b0da7f879fa9179 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 2 Dec 2020 09:16:08 +0800 Subject: [PATCH 04/64] library linking problem --- lib/node.js | 235 +++++++++++++----- rosidl_gen/idl_generator.js | 109 ++++++-- rosidl_gen/index.js | 42 ++-- rosidl_gen/templates/cppDefinitions.dot | 78 +++--- rosidl_gen/templates/cppDefinitionsHeader.dot | 5 + rosidl_gen/templates/typesupportGypi.dot | 3 + src/type_conversion.hpp | 41 ++- 7 files changed, 376 insertions(+), 137 deletions(-) diff --git a/lib/node.js b/lib/node.js index 78960ea3..7daf0717 100644 --- a/lib/node.js +++ b/lib/node.js @@ -23,7 +23,11 @@ const GuardCondition = require('./guard_condition.js'); const loader = require('./interface_loader.js'); const Logging = require('./logging.js'); const NodeOptions = require('./node_options.js'); -const { ParameterType, Parameter, ParameterDescriptor } = require('./parameter.js'); +const { + ParameterType, + Parameter, + ParameterDescriptor, +} = require('./parameter.js'); const ParameterService = require('./parameter_service.js'); const Publisher = require('./publisher.js'); const QoS = require('./qos.js'); @@ -74,7 +78,9 @@ class Node { if (options.parameterOverrides.length > 0) { for (const parameter of options.parameterOverrides) { if (!parameter instanceof Parameter) { - throw new TypeError('Parameter-override must be an instance of Parameter.'); + throw new TypeError( + 'Parameter-override must be an instance of Parameter.' + ); } this._parameterOverrides.set(parameter.name, parameter); } @@ -104,13 +110,21 @@ class Node { } execute(handles) { - let timersReady = this._timers.filter((timer) => handles.indexOf(timer.handle) !== -1); - let guardsReady = this._guards.filter((guard) => handles.indexOf(guard.handle) !== -1); + let timersReady = this._timers.filter( + (timer) => handles.indexOf(timer.handle) !== -1 + ); + let guardsReady = this._guards.filter( + (guard) => handles.indexOf(guard.handle) !== -1 + ); let subscriptionsReady = this._subscriptions.filter( (subscription) => handles.indexOf(subscription.handle) !== -1 ); - let clientsReady = this._clients.filter((client) => handles.indexOf(client.handle) !== -1); - let servicesReady = this._services.filter((service) => handles.indexOf(service.handle) !== -1); + let clientsReady = this._clients.filter( + (client) => handles.indexOf(client.handle) !== -1 + ); + let servicesReady = this._services.filter( + (service) => handles.indexOf(service.handle) !== -1 + ); let actionClientsReady = this._actionClients.filter( (actionClient) => handles.indexOf(actionClient.handle) !== -1 ); @@ -133,12 +147,15 @@ class Node { } return; } - this._runWithMessageType(subscription.typeClass, (message, deserialize) => { - let success = rclnodejs.rclTake(subscription.handle, message); - if (success) { - subscription.processResponse(deserialize()); + this._runWithMessageType( + subscription.typeClass, + (message, deserialize) => { + let success = rclnodejs.rclTake(subscription.handle, message); + if (success) { + subscription.processResponse(deserialize()); + } } - }); + ); }); guardsReady.forEach((guard) => { @@ -146,21 +163,35 @@ class Node { }); clientsReady.forEach((client) => { - this._runWithMessageType(client.typeClass.Response, (message, deserialize) => { - let success = rclnodejs.rclTakeResponse(client.handle, client.sequenceNumber, message); - if (success) { - client.processResponse(deserialize()); + this._runWithMessageType( + client.typeClass.Response, + (message, deserialize) => { + let success = rclnodejs.rclTakeResponse( + client.handle, + client.sequenceNumber, + message + ); + if (success) { + client.processResponse(deserialize()); + } } - }); + ); }); servicesReady.forEach((service) => { - this._runWithMessageType(service.typeClass.Request, (message, deserialize) => { - let header = rclnodejs.rclTakeRequest(service.handle, this.handle, message); - if (header) { - service.processRequest(header, deserialize()); + this._runWithMessageType( + service.typeClass.Request, + (message, deserialize) => { + let header = rclnodejs.rclTakeRequest( + service.handle, + this.handle, + message + ); + if (header) { + service.processRequest(header, deserialize()); + } } - }); + ); }); actionClientsReady.forEach((actionClient) => { @@ -170,7 +201,10 @@ class Node { this._runWithMessageType( actionClient.typeClass.impl.SendGoalService.Response, (message, deserialize) => { - let sequence = rclnodejs.actionTakeGoalResponse(actionClient.handle, message); + let sequence = rclnodejs.actionTakeGoalResponse( + actionClient.handle, + message + ); if (sequence != null) { actionClient.processGoalResponse(sequence, deserialize()); } @@ -182,7 +216,10 @@ class Node { this._runWithMessageType( actionClient.typeClass.impl.CancelGoal.Response, (message, deserialize) => { - let sequence = rclnodejs.actionTakeCancelResponse(actionClient.handle, message); + let sequence = rclnodejs.actionTakeCancelResponse( + actionClient.handle, + message + ); if (sequence != null) { actionClient.processCancelResponse(sequence, deserialize()); } @@ -194,7 +231,10 @@ class Node { this._runWithMessageType( actionClient.typeClass.impl.GetResultService.Response, (message, deserialize) => { - let sequence = rclnodejs.actionTakeResultResponse(actionClient.handle, message); + let sequence = rclnodejs.actionTakeResultResponse( + actionClient.handle, + message + ); if (sequence != null) { actionClient.processResultResponse(sequence, deserialize()); } @@ -206,7 +246,10 @@ class Node { this._runWithMessageType( actionClient.typeClass.impl.FeedbackMessage, (message, deserialize) => { - let success = rclnodejs.actionTakeFeedback(actionClient.handle, message); + let success = rclnodejs.actionTakeFeedback( + actionClient.handle, + message + ); if (success) { actionClient.processFeedbackMessage(deserialize()); } @@ -218,7 +261,10 @@ class Node { this._runWithMessageType( actionClient.typeClass.impl.GoalStatusArray, (message, deserialize) => { - let success = rclnodejs.actionTakeStatus(actionClient.handle, message); + let success = rclnodejs.actionTakeStatus( + actionClient.handle, + message + ); if (success) { actionClient.processStatusMessage(deserialize()); } @@ -234,7 +280,10 @@ class Node { this._runWithMessageType( actionServer.typeClass.impl.SendGoalService.Request, (message, deserialize) => { - const result = rclnodejs.actionTakeGoalRequest(actionServer.handle, message); + const result = rclnodejs.actionTakeGoalRequest( + actionServer.handle, + message + ); if (result) { actionServer.processGoalRequest(result, deserialize()); } @@ -246,7 +295,10 @@ class Node { this._runWithMessageType( actionServer.typeClass.impl.CancelGoal.Request, (message, deserialize) => { - const result = rclnodejs.actionTakeCancelRequest(actionServer.handle, message); + const result = rclnodejs.actionTakeCancelRequest( + actionServer.handle, + message + ); if (result) { actionServer.processCancelRequest(result, deserialize()); } @@ -258,7 +310,10 @@ class Node { this._runWithMessageType( actionServer.typeClass.impl.GetResultService.Request, (message, deserialize) => { - const result = rclnodejs.actionTakeResultRequest(actionServer.handle, message); + const result = rclnodejs.actionTakeResultRequest( + actionServer.handle, + message + ); if (result) { actionServer.processResultRequest(result, deserialize()); } @@ -308,7 +363,10 @@ class Node { } _validateOptions(options) { - if (options !== undefined && (options === null || typeof options !== 'object')) { + if ( + options !== undefined && + (options === null || typeof options !== 'object') + ) { throw new TypeError('Invalid argument of options'); } @@ -360,13 +418,20 @@ class Node { const MAX_TIMER_PERIOD_IN_MILLISECOND = 0x10c6f7a0b5ed; if (period > 0x10c6f7a0b5ed || period < 0) { throw new RangeError( - 'Parameter must be between ' + 0 + ' and ' + MAX_TIMER_PERIOD_IN_MILLISECOND + 'Parameter must be between ' + + 0 + + ' and ' + + MAX_TIMER_PERIOD_IN_MILLISECOND ); } const timerClock = clock || this._clock; - let timerHandle = rclnodejs.createTimer(timerClock.handle, this.context.handle, period); + let timerHandle = rclnodejs.createTimer( + timerClock.handle, + this.context.handle, + period + ); let timer = new Timer(timerHandle, period, callback); debug('Finish creating timer, period = %d.', period); this._timers.push(timer); @@ -388,7 +453,9 @@ class Node { const MAX_RATE_HZ_IN_MILLISECOND = 1000.0; if (hz <= 0.0 || hz > MAX_RATE_HZ_IN_MILLISECOND) { - throw new RangeError(`Hz must be between 0.0 and ${MAX_RATE_HZ_IN_MILLISECOND}`); + throw new RangeError( + `Hz must be between 0.0 and ${MAX_RATE_HZ_IN_MILLISECOND}` + ); } // lazy initialize rateTimerServer @@ -518,7 +585,12 @@ class Node { throw new TypeError('Invalid argument'); } - let client = Client.createClient(this.handle, serviceName, typeClass, options); + let client = Client.createClient( + this.handle, + serviceName, + typeClass, + options + ); debug('Finish creating client, service = %s.', serviceName); this._clients.push(client); this.syncHandles(); @@ -754,7 +826,12 @@ class Node { * @return {array} - An array of the names and types. */ getPublisherNamesAndTypesByNode(nodeName, namespace, noDemangle = false) { - return rclnodejs.getPublisherNamesAndTypesByNode(this.handle, nodeName, namespace, noDemangle); + return rclnodejs.getPublisherNamesAndTypesByNode( + this.handle, + nodeName, + namespace, + noDemangle + ); } /** @@ -780,7 +857,11 @@ class Node { * @return {array} - An array of the names and types. */ getServiceNamesAndTypesByNode(nodeName, namespace) { - return rclnodejs.getServiceNamesAndTypesByNode(this.handle, nodeName, namespace); + return rclnodejs.getServiceNamesAndTypesByNode( + this.handle, + nodeName, + namespace + ); } /** @@ -822,7 +903,11 @@ class Node { * @returns {number} - Number of publishers on the given topic. */ countPublishers(topic) { - let expandedTopic = rclnodejs.expandTopicName(topic, this.name(), this.namespace()); + let expandedTopic = rclnodejs.expandTopicName( + topic, + this.name(), + this.namespace() + ); rclnodejs.validateTopicName(expandedTopic); return rclnodejs.countPublishers(this.handle, expandedTopic); @@ -834,7 +919,11 @@ class Node { * @returns {number} - Number of subscribers on the given topic. */ countSubscribers(topic) { - let expandedTopic = rclnodejs.expandTopicName(topic, this.name(), this.namespace()); + let expandedTopic = rclnodejs.expandTopicName( + topic, + this.name(), + this.namespace() + ); rclnodejs.validateTopicName(expandedTopic); return rclnodejs.countSubscribers(this.handle, expandedTopic); @@ -915,10 +1004,14 @@ class Node { throw new TypeError('Invalid parameter: expected array of Parameter'); } if (!Array.isArray(descriptors)) { - throw new TypeError('Invalid parameters: expected array of ParameterDescriptor'); + throw new TypeError( + 'Invalid parameters: expected array of ParameterDescriptor' + ); } if (descriptors.length > 0 && parameters.length !== descriptors.length) { - throw new TypeError('Each parameter must have a cooresponding ParameterDescriptor'); + throw new TypeError( + 'Each parameter must have a cooresponding ParameterDescriptor' + ); } const declaredDescriptors = []; @@ -938,7 +1031,9 @@ class Node { // create descriptor for parameter if not provided let descriptor = - descriptors.length > 0 ? descriptors[i] : ParameterDescriptor.fromParameter(parameter); + descriptors.length > 0 + ? descriptors[i] + : ParameterDescriptor.fromParameter(parameter); descriptor.validate(); @@ -984,7 +1079,9 @@ class Node { const descriptor = this.getParameterDescriptor(name); if (descriptor.readOnly) { - throw new Error(`${name} parameter is read-only and can not be undeclared`); + throw new Error( + `${name} parameter is read-only and can not be undeclared` + ); } this._parameters.delete(name); @@ -1105,7 +1202,10 @@ class Node { for (const name of names) { let descriptor = this._parameterDescriptors.get(name); if (!descriptor) { - descriptor = new ParameterDescriptor(name, ParameterType.PARAMETER_NOT_SET); + descriptor = new ParameterDescriptor( + name, + ParameterType.PARAMETER_NOT_SET + ); } descriptors.push(descriptor); } @@ -1147,7 +1247,9 @@ class Node { * @return {rclnodejs.rcl_interfaces.msg.SetParameterResult[]} - A list of SetParameterResult, one for each parameter that was set. */ setParameters(parameters = []) { - return parameters.map((parameter) => this.setParametersAtomically([parameter])); + return parameters.map((parameter) => + this.setParametersAtomically([parameter]) + ); } /** @@ -1225,7 +1327,9 @@ class Node { } // create ParameterEvent - const parameterEvent = new (loader.loadInterface(PARAMETER_EVENT_MSG_TYPE))(); + const parameterEvent = new (loader.loadInterface( + PARAMETER_EVENT_MSG_TYPE + ))(); const secondsAndNanos = this._clock.now().secondsAndNanoseconds; parameterEvent.stamp = { @@ -1244,14 +1348,14 @@ class Node { ); } if (changedParameters.length > 0) { - parameterEvent['changed_parameters'] = changedParameters.map((parameter) => - parameter.toParameterMessage() - ); + parameterEvent[ + 'changed_parameters' + ] = changedParameters.map((parameter) => parameter.toParameterMessage()); } if (deletedParameters.length > 0) { - parameterEvent['deleted_parameters'] = deletedParameters.map((parameter) => - parameter.toParameterMessage() - ); + parameterEvent[ + 'deleted_parameters' + ] = deletedParameters.map((parameter) => parameter.toParameterMessage()); } // publish ParameterEvent @@ -1366,7 +1470,9 @@ class Node { // type: uint // value: object // } - const cliParamOverrideData = rclnodejs.getParameterOverrides(context.handle); + const cliParamOverrideData = rclnodejs.getParameterOverrides( + context.handle + ); // convert native CLI parameterOverrides to Map> const cliParamOverrides = new Map(); @@ -1375,7 +1481,11 @@ class Node { const nodeName = nodeParamData.name; const nodeParamOverrides = []; for (let paramData of nodeParamData.parameters) { - const paramOverride = new Parameter(paramData.name, paramData.type, paramData.value); + const paramOverride = new Parameter( + paramData.name, + paramData.type, + paramData.value + ); nodeParamOverrides.push(paramOverride); } cliParamOverrides.set(nodeName, nodeParamOverrides); @@ -1410,16 +1520,21 @@ class Node { * @returns {undefined} */ _runWithMessageType(Type, callback) { - let message = new Type(); + if (process.env.RCLNODEJS_USE_ROS_SERIALIZATION) { + let message = Type.create(); + callback(message, () => Type.ToJsObject(message)); + } else { + let message = new Type(); - callback(message.toRawROS(), () => { - let result = new Type(); - result.deserialize(message.refObject); + callback(message.toRawROS(), () => { + let result = new Type(); + result.deserialize(message.refObject); - return result; - }); + return result; + }); - Type.destoryRawROS(message); + Type.destoryRawROS(message); + } } _addActionClient(actionClient) { diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index a588e00f..6ceacf72 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -23,8 +23,10 @@ const actionMsgs = require('./action_msgs.js'); class RosIdlDb { constructor(pkgs) { - this.specDb = {}; + this.pkgIndex = pkgs; + this.specIndex = {}; this.messageInfoIndex = {}; + this.dependentPackagesIndex = {}; for (let pkg of pkgs.values()) { pkg.messages.forEach((messageInfo) => { this.messageInfoIndex[ @@ -38,12 +40,35 @@ class RosIdlDb { return this.messageInfoIndex[`${type.pkgName}__${type.type}`]; } + async getDependentMessages(pkgName) { + let dependentPackages = this.dependentPackagesIndex[pkgName]; + if (dependentPackages === undefined) { + this.dependentPackagesIndex[pkgName] = new Promise(async (res) => { + const set = new Set(); + const pkgInfo = this.pkgIndex.get(pkgName); + for (let messageInfo of pkgInfo.messages) { + const spec = await this.getMessageSpec(messageInfo); + spec.fields.forEach((field) => { + if (field.type.pkgName && field.type.pkgName !== pkgName) { + // `this.getMessageInfoFromType` must always return the + // same object for the same type for this to work + set.add(this.getMessageInfoFromType(field.type)); + } + }); + } + res(Array.from(set.values())); + }); + return this.dependentPackagesIndex[pkgName]; + } + return dependentPackages; + } + _messageInfoHash(messageInfo) { return `${messageInfo.pkgName}__${messageInfo.interfaceName}`; } async getMessageSpec(messageInfo) { - let spec = this.specDb[this._messageInfoHash(messageInfo)]; + let spec = this.specIndex[this._messageInfoHash(messageInfo)]; if (spec) { return spec; } @@ -52,10 +77,10 @@ class RosIdlDb { messageInfo.pkgName, messageInfo.filePath ); - this.specDb[this._messageInfoHash(messageInfo)] = spec; + this.specIndex[this._messageInfoHash(messageInfo)] = spec; res(spec); }); - this.specDb[this._messageInfoHash(messageInfo)] = promise; + this.specIndex[this._messageInfoHash(messageInfo)] = promise; return promise; } @@ -75,10 +100,9 @@ const dots = dot.process({ }); function pascalToSnakeCase(s) { - return s - .split(/(?=[A-Z])/) - .join('_') - .toLowerCase(); + let result = s.replace(/(.)([A-Z][a-z]+)/g, '$1_$2'); + result = result.replace(/([a-z0-9])([A-Z])/g, '$1_$2'); + return result.toLowerCase(); } function getRosHeaderField(messageInfo) { @@ -136,12 +160,8 @@ function generateMessageJSStructFromSpec(messageInfo, dir, spec) { return writeGeneratedCode(dir, fileName, generatedCode); } -function getCppSourcePath(pkgName) { - return path.join('src', 'generated', pkgName, 'definitions.cpp'); -} - -function getCppHeaderPath(pkgName) { - return path.join('src', 'generated', pkgName, 'definitions.hpp'); +function getCppOutputDir(pkgName) { + return path.join('src', 'generated', pkgName); } function getJsType(rosType) { @@ -167,12 +187,19 @@ function getJsType(rosType) { return 'object'; } +function isServiceMessage(messageInfo) { + return ( + messageInfo.interfaceName.endsWith('_Request') || + messageInfo.interfaceName.endsWith('_Response') + ); +} + +function isInternalField(field) { + return field.name.startsWith('_'); +} + // All messages are combined in one cpp file to improve compile time. async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { - // console.log(messageInfo); - // console.log(spec); - // console.log(spec.fields); - const getStructType = (messageInfo) => { return `${messageInfo.pkgName}__${messageInfo.subFolder}__${messageInfo.interfaceName}`; }; @@ -186,34 +213,51 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { // this is slower but doing it sequentially maintains ordering for (let messageInfo of pkgInfo.messages) { - messages.push({ - info: messageInfo, - spec: await rosIdlDb.getMessageSpec(messageInfo), - structType: getStructType(messageInfo), - }); + if (!isServiceMessage(messageInfo)) { + messages.push({ + info: messageInfo, + spec: await rosIdlDb.getMessageSpec(messageInfo), + structType: getStructType(messageInfo), + }); + } } + const dependentMessages = await rosIdlDb.getDependentMessages(pkgName); + const source = removeEmptyLines( dots.cppDefinitions({ + pkgName, + pkgInfo, messages, + dependentMessages, rosIdlDb, + getStructType, getRosHeaderField, getStructTypeFromRosType, getJsType, + isInternalField, }) ); const header = removeEmptyLines( dots.cppDefinitionsHeader({ + pkgName, + pkgInfo, messages, + dependentMessages, rosIdlDb, + getStructType, getRosHeaderField, getStructTypeFromRosType, + getJsType, + isInternalField, }) ); - await fs.writeFile(getCppSourcePath(pkgName), source); - await fs.writeFile(getCppHeaderPath(pkgName), header); + const outputDir = getCppOutputDir(pkgName); + await fs.mkdir(outputDir, { recursive: true }); + await fs.writeFile(path.join(outputDir, 'definitions.cpp'), source); + await fs.writeFile(path.join(outputDir, 'definitions.hpp'), header); } async function generateActionJSStruct(actionInfo, dir) { @@ -380,8 +424,19 @@ async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { ]); } -async function generateTypesupportGypi(pkgs) { - const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); +async function generateTypesupportGypi(pkgsEntries) { + const pkgs = []; + for (let [pkgName, pkgInfo] of pkgsEntries) { + if (await fs.stat()) + } + const rendered = removeEmptyLines( + dots.typesupportGypi({ + pkgs: pkgsEntries.map(([pkgName, pkgInfo]) => ({ + pkgName, + pkgInfo, + })), + }) + ); await fs.writeFile( path.join('src', 'generated', 'typesupport.gypi'), rendered diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 54b41667..29d4b7e9 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -30,26 +30,26 @@ const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split( ); async function generateInPath(path) { - const results = []; - // const pkgs = await packages.findPackagesInDirectory(path); - const pkgs = new Map(); - pkgs.set('test_msgs', { - pkgName: 'test_msgs', - messages: [ - { - interfaceName: 'Nested', - subFolder: 'msg', - filePath: '/opt/ros/foxy/share/test_msgs/msg/Nested.msg', - }, - { - interfaceName: 'BasicTypes', - subFolder: 'msg', - filePath: '/opt/ros/foxy/share/test_msgs/msg/BasicTypes.msg', - }, - ], - services: [], - actions: [], - }); + const pkgs = await packages.findPackagesInDirectory(path); + // const pkgs = new Map(); + // pkgs.set('test_msgs', { + // messages: [ + // { + // pkgName: 'test_msgs', + // interfaceName: 'Nested', + // subFolder: 'msg', + // filePath: '/opt/ros/foxy/share/test_msgs/msg/Nested.msg', + // }, + // { + // pkgName: 'test_msgs', + // interfaceName: 'BasicTypes', + // subFolder: 'msg', + // filePath: '/opt/ros/foxy/share/test_msgs/msg/BasicTypes.msg', + // }, + // ], + // services: [], + // actions: [], + // }); const rosIdlDb = new RosIdlDb(pkgs); @@ -66,7 +66,7 @@ async function generateInPath(path) { generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) ) ); - await generateTypesupportGypi(pkgsInfo); + await generateTypesupportGypi(pkgsEntries); } async function generateAll(forcedGenerating) { diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 2ce7948e..f7bff807 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -6,54 +6,68 @@ #include "definitions.hpp" #include "../../type_conversion.hpp" -{{~ it.messages : message }} +{{~ it.dependentMessages : messageInfo}} +#include "../{{=messageInfo.pkgName}}/definitions.hpp" +{{~}} + +{{~ it.messages : message}} #include <{{=it.getRosHeaderField(message.info)}}> {{~}} +{{~ it.dependentMessages : messageInfo}} +struct {{=it.getStructType(messageInfo)}}; +{{~}} namespace rclnodejs { -{{~ it.messages : message }} +{{~ it.messages : message}} NAN_MODULE_INIT(rclnodejs__{{=message.structType}}::Init) { auto obj = Nan::New(); - obj->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); - obj->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); - obj->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); - Nan::Set(target, Nan::New("{{=message.structType}}").ToLocalChecked(), obj); + obj->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); + obj->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); + obj->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); + Nan::Set(target, Nan::New("{{=message.info.interfaceName}}").ToLocalChecked(), obj); } void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsObj, {{=message.structType}}* msg) { {{~ message.spec.fields : field}} - auto {{=field.name}} = jsObj->Get(Nan::New("{{=field.name}}").ToLocalChecked()); +{{? !it.isInternalField(field)}} + { + // end with underscore so it doesn't conflicts with field names + auto js_value_ = jsObj->Get(Nan::New("{{=field.name}}").ToLocalChecked()); {{ - const jsType = it.getJsType(field.type); + const jsType = it.getJsType(field.type); }} {{? jsType === 'number'}} - if (!{{=field.name}}->IsNumber()) { - throw new std::runtime_error("expected {{=field.name}} to be number"); - } + if (!js_value_->IsNumber()) { + throw new std::runtime_error("expected {{=field.name}} to be number"); + } {{?? jsType === 'string'}} - if (!{{=field.name}}->IsString()) { - throw new std::runtime_error("expected {{=field.name}} to be string"); - } + if (!js_value_->IsString()) { + throw new std::runtime_error("expected {{=field.name}} to be string"); + } {{?? jsType === 'boolean'}} - if (!{{=field.name}}->IsBoolean()) { - throw new std::runtime_error("expected {{=field.name}} to be boolean"); - } + if (!js_value_->IsBoolean()) { + throw new std::runtime_error("expected {{=field.name}} to be boolean"); + } {{?? jsType === 'bigint'}} - if (!{{=field.name}}->IsBigInt()) { - throw new std::runtime_error("expected {{=field.name}} to be bigint"); - } + if (!js_value_->IsBigInt()) { + throw new std::runtime_error("expected {{=field.name}} to be bigint"); + } {{??}} - if (!{{=field.name}}->IsObject()) { - throw new std::runtime_error("expected {{=field.name}} to be {{=field.type.type}} object"); - } + if (!js_value_->IsObject()) { + throw new std::runtime_error("expected {{=field.name}} to be {{=field.type.type}} object"); + } +{{?}} +{{? !field.type.isArray}} +{{? field.type.isPrimitiveType}} + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value_); +{{??}} + rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::WriteMessage(Nan::To(js_value_).ToLocalChecked(), &msg->{{=field.name}}); {{?}} -{{? field.type.isPrimitiveType && !field.type.isArray}} - msg->{{=field.name}} = ToNativeChecked{{=field.name}})>({{=field.name}}); -{{?? !field.type.isPrimitiveType}} - rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::WriteMessage(Nan::To({{=field.name}}).ToLocalChecked(), &msg->{{=field.name}}); {{??}} - // TODO: handle array types + // TODO: handle array types +{{?}} + } {{?}} {{~}} } @@ -61,6 +75,7 @@ void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsOb v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=message.structType}}* msg) { auto jsObj = Nan::New(); {{~ message.spec.fields : field}} +{{? !it.isInternalField(field)}} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} jsObj->Set(Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); @@ -70,6 +85,7 @@ v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=messag {{??}} // TODO: handle array {{?}} +{{?}} {{~}} return jsObj; } @@ -108,4 +124,10 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { {{~}} +NAN_MODULE_WORKER_ENABLED({{=it.pkgName}}, [](auto target) { +{{~ it.messages : message}} + rclnodejs__{{=message.structType}}::Init(target); +{{~}} +}); + } // namespace rclnodejs diff --git a/rosidl_gen/templates/cppDefinitionsHeader.dot b/rosidl_gen/templates/cppDefinitionsHeader.dot index 2e6ec676..b6585174 100644 --- a/rosidl_gen/templates/cppDefinitionsHeader.dot +++ b/rosidl_gen/templates/cppDefinitionsHeader.dot @@ -3,6 +3,9 @@ // *** DO NOT EDIT directly // +#ifndef RCLNODEJS_{{=it.pkgName.toUpperCase()}}_DEFINITIONS_HPP_ +#define RCLNODEJS_{{=it.pkgName.toUpperCase()}}_DEFINITIONS_HPP_ + #include {{~ it.messages : message}} @@ -33,3 +36,5 @@ class rclnodejs__{{=message.structType}} { {{~}} } // namespace rclnodejs + +#endif diff --git a/rosidl_gen/templates/typesupportGypi.dot b/rosidl_gen/templates/typesupportGypi.dot index 37bd3efa..77988a43 100644 --- a/rosidl_gen/templates/typesupportGypi.dot +++ b/rosidl_gen/templates/typesupportGypi.dot @@ -6,6 +6,9 @@ 'sources': [ '{{=pkg.pkgName}}/definitions.cpp', ], + 'libraries': [ + '-l{{=pkg.pkgName}}__rosidl_typesupport_c', + ], }, {{~}} ], diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index c55d8495..3f58fe58 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -2,6 +2,10 @@ #define RCLNODEJS_TYPE_CONVERSION_HPP_ #include +#include +#include +#include +#include namespace rclnodejs { @@ -47,6 +51,25 @@ inline float ToNativeChecked(v8::Local val) { return Nan::To(std::move(val)).ToChecked(); } +template <> +inline rosidl_runtime_c__String ToNativeChecked( + v8::Local val) { + Nan::Utf8String utf8(val); + if (*utf8 == nullptr) { + throw std::runtime_error("failed to convert value to string"); + } + rosidl_runtime_c__String ros_string; + rosidl_runtime_c__String__assign(&ros_string, *utf8); + return ros_string; +} + +template <> +inline rosidl_runtime_c__U16String ToNativeChecked( + v8::Local val) { + // TODO: + throw std::runtime_error("not implemented"); +} + template inline v8::Local ToJsChecked(T val) { return Nan::New(val); @@ -59,7 +82,23 @@ inline v8::Local ToJsChecked(int64_t val) { template <> inline v8::Local ToJsChecked(uint64_t val) { - return v8::BigInt::NewFromUnsigned(Nan::GetCurrentContext()->GetIsolate(), val); + return v8::BigInt::NewFromUnsigned(Nan::GetCurrentContext()->GetIsolate(), + val); +} + +// can't specialize const ref, probably need to use SFINAE +template <> +inline v8::Local ToJsChecked( + rosidl_runtime_c__String val) { + return Nan::New(val.data).ToLocalChecked(); +} + +// can't specialize const ref, probably need to use SFINAE +template <> +inline v8::Local ToJsChecked( + rosidl_runtime_c__U16String val) { + // TODO: + throw new std::runtime_error("not implemented"); } } // namespace rclnodejs From 751705e9f2aa919d9cf947be38e614e18b8a9a70 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 4 Dec 2020 16:27:21 +0800 Subject: [PATCH 05/64] using regex on the cmake files to find link libraries --- package.json | 2 +- rosidl_gen/idl_generator.js | 61 +++++++++++++++++++----- rosidl_gen/index.js | 2 +- rosidl_gen/templates/typesupportGypi.dot | 4 +- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index f55e4c22..f0cf217a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "typescript" ], "scripts": { - "install": "node-gyp rebuild", + "install": "node scripts/generate_messages.js && node-gyp rebuild", "docs": "cd docs && make", "test": "node ./scripts/compile_tests.js && node --expose-gc ./scripts/run_test.js && npm run dtslint", "dtslint": "node ./scripts/generate_tsd.js && dtslint test/types", diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 6ceacf72..68b136dd 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -424,19 +424,58 @@ async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { ]); } -async function generateTypesupportGypi(pkgsEntries) { - const pkgs = []; - for (let [pkgName, pkgInfo] of pkgsEntries) { - if (await fs.stat()) +/** + * Tries to guess the libraries needed to be linked against for typesupport_c. + * + * Normally, the typesupport libraries are built at compiled time of the message packages. The + * libraries that have to be linked against are based on the name of the cmake target. Because + * + * 1. We are a third party library, so our typesupport cannot be built at the compile time. + * 2. We are use node-gyp as the build tool, so we can't use cmake to find the link libraries. + * + * The stopgap solution is then to use regexp on the cmake config files to try to find the + * required link libraries. + * + * @param {string} pkg name of the package + * @param {string} amentRoot ament root directory + * @returns {string[]} an array of typesupport_c libraries found + */ +async function guessTypesupportCLibs(pkg, amentRoot) { + const cmakeExport = await fs.readFile( + path.join( + amentRoot, + 'share', + pkg, + 'cmake', + 'ament_cmake_export_libraries-extras.cmake' + ), + 'utf-8' + ); + const match = cmakeExport.match( + /set\s*\(\s*(?:_exported_typesupport_libraries|_exported_libraries)\s*"(.*)"/ + ); + if (!match || match.length < 2) { + throw new Error(`unable to find typesupport library for ${pkg}`); } - const rendered = removeEmptyLines( - dots.typesupportGypi({ - pkgs: pkgsEntries.map(([pkgName, pkgInfo]) => ({ - pkgName, - pkgInfo, - })), - }) + const libraries = match[1].replace(/:/g, ';'); + const typesupportCLibs = []; + libraries.split(';').forEach((lib) => { + if (lib.endsWith('rosidl_typesupport_c')) { + typesupportCLibs.push(lib); + } + }); + return typesupportCLibs; +} + +async function generateTypesupportGypi(pkgsEntries, amentRoot) { + const pkgs = await Promise.all( + pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ + pkgName, + pkgInfo, + typesupportLibs: await guessTypesupportCLibs(pkgName, amentRoot), + })) ); + const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); await fs.writeFile( path.join('src', 'generated', 'typesupport.gypi'), rendered diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 29d4b7e9..ba3ba7f5 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -66,7 +66,7 @@ async function generateInPath(path) { generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) ) ); - await generateTypesupportGypi(pkgsEntries); + await generateTypesupportGypi(pkgsEntries, path); } async function generateAll(forcedGenerating) { diff --git a/rosidl_gen/templates/typesupportGypi.dot b/rosidl_gen/templates/typesupportGypi.dot index 77988a43..217ae5e9 100644 --- a/rosidl_gen/templates/typesupportGypi.dot +++ b/rosidl_gen/templates/typesupportGypi.dot @@ -7,7 +7,9 @@ '{{=pkg.pkgName}}/definitions.cpp', ], 'libraries': [ - '-l{{=pkg.pkgName}}__rosidl_typesupport_c', +{{~ pkg.typesupportLibs : lib}} + '-l{{=lib}}', +{{~}} ], }, {{~}} From 24d9ef7c1c43142583977006c26b9add8079867f Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 4 Dec 2020 17:01:53 +0800 Subject: [PATCH 06/64] collect all packages from all paths before generating, this is needed to generate typesupport gypi --- rosidl_gen/idl_generator.js | 4 ++-- rosidl_gen/index.js | 42 ++++++++++++++----------------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 68b136dd..72b60b21 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -467,12 +467,12 @@ async function guessTypesupportCLibs(pkg, amentRoot) { return typesupportCLibs; } -async function generateTypesupportGypi(pkgsEntries, amentRoot) { +async function generateTypesupportGypi(pkgsEntries) { const pkgs = await Promise.all( pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ pkgName, pkgInfo, - typesupportLibs: await guessTypesupportCLibs(pkgName, amentRoot), + typesupportLibs: await guessTypesupportCLibs(pkgName, pkgInfo.amentRoot), })) ); const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index ba3ba7f5..1c3dfec1 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -29,27 +29,16 @@ const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split( path.delimiter ); -async function generateInPath(path) { - const pkgs = await packages.findPackagesInDirectory(path); - // const pkgs = new Map(); - // pkgs.set('test_msgs', { - // messages: [ - // { - // pkgName: 'test_msgs', - // interfaceName: 'Nested', - // subFolder: 'msg', - // filePath: '/opt/ros/foxy/share/test_msgs/msg/Nested.msg', - // }, - // { - // pkgName: 'test_msgs', - // interfaceName: 'BasicTypes', - // subFolder: 'msg', - // filePath: '/opt/ros/foxy/share/test_msgs/msg/BasicTypes.msg', - // }, - // ], - // services: [], - // actions: [], - // }); +async function generateInPaths(paths) { + const pkgsInPaths = await Promise.all( + paths.map((path) => packages.findPackagesInDirectory(path)) + ); + const pkgs = new Map(); + pkgsInPaths.forEach((m, i) => { + for (let [pkgName, pkgInfo] of m.entries()) { + pkgs.set(pkgName, { ...pkgInfo, amentRoot: paths[i] }); + } + }); const rosIdlDb = new RosIdlDb(pkgs); @@ -66,7 +55,7 @@ async function generateInPath(path) { generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) ) ); - await generateTypesupportGypi(pkgsEntries, path); + await generateTypesupportGypi(pkgsEntries); } async function generateAll(forcedGenerating) { @@ -79,9 +68,10 @@ async function generateAll(forcedGenerating) { path.join(__dirname, 'generator.json'), path.join(generatedRoot, 'generator.json') ); - await Promise.all( - installedPackagePaths.map((path) => generateInPath(path)) - ); + await generateInPaths(installedPackagePaths); + // await Promise.all( + // installedPackagePaths.map((path) => generateInPath(path)) + // ); } } @@ -92,7 +82,7 @@ const generator = { }, generateAll, - generateInPath, + generateInPaths, generatedRoot, }; From de5563120c633137ec38468f63e75e0187f40dda Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 08:58:30 +0800 Subject: [PATCH 07/64] remove package-lock --- package-lock.json | 4607 --------------------------------------------- 1 file changed, 4607 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index bd06aa69..00000000 --- a/package-lock.json +++ /dev/null @@ -1,4607 +0,0 @@ -{ - "name": "rclnodejs", - "version": "0.16.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - } - } - }, - "@definitelytyped/header-parser": { - "version": "0.0.57", - "resolved": "https://registry.npmjs.org/@definitelytyped/header-parser/-/header-parser-0.0.57.tgz", - "integrity": "sha512-0CNcUUANv93072vleKkXKT8xUNk9JLhaHVMZbBYP/km55T+V8eGCP6BS0pS80MPhvZouq2FmR/r8B5jlR+MQ8w==", - "dev": true, - "requires": { - "@definitelytyped/typescript-versions": "^0.0.57", - "@types/parsimmon": "^1.10.1", - "parsimmon": "^1.13.0" - } - }, - "@definitelytyped/typescript-versions": { - "version": "0.0.57", - "resolved": "https://registry.npmjs.org/@definitelytyped/typescript-versions/-/typescript-versions-0.0.57.tgz", - "integrity": "sha512-PpA1dLjH//4fvZ6P5RVR10n+it0lBp/so3dgSAHdFmtHU42kPFc2TlwIYSDL0P5DcNVYViAwIvIIVbYF9hbD+Q==", - "dev": true - }, - "@definitelytyped/utils": { - "version": "0.0.57", - "resolved": "https://registry.npmjs.org/@definitelytyped/utils/-/utils-0.0.57.tgz", - "integrity": "sha512-YEIxwB2Im0GQ0lapCpoW+m3XeQqctf0aueuVbm2lNESZCVMgLXVSFaTIquhgKcp/KW+HzVldwH7RyEnbTZiWQw==", - "dev": true, - "requires": { - "@definitelytyped/typescript-versions": "^0.0.57", - "@types/node": "^12.12.29", - "charm": "^1.0.2", - "fs-extra": "^8.1.0", - "fstream": "^1.0.12", - "npm-registry-client": "^8.6.0", - "tar": "^2.2.2", - "tar-stream": "1.6.2" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } - } - }, - "@eslint/eslintrc": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", - "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "@sinonjs/samsam": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.1.0.tgz", - "integrity": "sha512-42nyaQOVunX5Pm6GRJobmzbS7iLI+fhERITnETXzzwDZh+TtDr/Au3yAvXVjFmZ4wEUaE4Y3NFZfKv0bV0cbtg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true - }, - "@types/node": { - "version": "12.12.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.68.tgz", - "integrity": "sha512-3RW2s24ewB7F9dAHvgb9FRvNHn6nO9IK6Eaknbz7HTOe2a5GVne5XbUh5+YA+kcCn67glyHhClUUdFP73LWrgQ==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/parsimmon": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@types/parsimmon/-/parsimmon-1.10.3.tgz", - "integrity": "sha512-BbCYdfYC/XFsVkjWJCeCaUaeYlMHNJ2HmZYaCbsZ14k6qO/mX6n3u2sgtJxSeJLiDPaxb1LESgGA/qGP+AHSCQ==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz", - "integrity": "sha512-li9aiSVBBd7kU5VlQlT1AqP0uWGDK6JYKUQ9cVDnOg34VNnd9t4jr0Yqc/bKxJr/tDCPDaB4KzoSFN9fgVxe/Q==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.7.0", - "@typescript-eslint/scope-manager": "4.7.0", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.7.0.tgz", - "integrity": "sha512-cymzovXAiD4EF+YoHAB5Oh02MpnXjvyaOb+v+BdpY7lsJXZQN34oIETeUwVT2XfV9rSNpXaIcknDLfupO/tUoA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.7.0", - "@typescript-eslint/types": "4.7.0", - "@typescript-eslint/typescript-estree": "4.7.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.7.0.tgz", - "integrity": "sha512-+meGV8bMP1sJHBI2AFq1GeTwofcGiur8LoIr6v+rEmD9knyCqDlrQcFHR0KDDfldHIFDU/enZ53fla6ReF4wRw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.7.0", - "@typescript-eslint/types": "4.7.0", - "@typescript-eslint/typescript-estree": "4.7.0", - "debug": "^4.1.1" - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.7.0.tgz", - "integrity": "sha512-ILITvqwDJYbcDCROj6+Ob0oCKNg3SH46iWcNcTIT9B5aiVssoTYkhKjxOMNzR1F7WSJkik4zmuqve5MdnA0DyA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.7.0", - "@typescript-eslint/visitor-keys": "4.7.0" - } - }, - "@typescript-eslint/types": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.7.0.tgz", - "integrity": "sha512-uLszFe0wExJc+I7q0Z/+BnP7wao/kzX0hB5vJn4LIgrfrMLgnB2UXoReV19lkJQS1a1mHWGGODSxnBx6JQC3Sg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.7.0.tgz", - "integrity": "sha512-5XZRQznD1MfUmxu1t8/j2Af4OxbA7EFU2rbo0No7meb46eHgGkSieFdfV6omiC/DGIBhH9H9gXn7okBbVOm8jw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.7.0", - "@typescript-eslint/visitor-keys": "4.7.0", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.7.0.tgz", - "integrity": "sha512-aDJDWuCRsf1lXOtignlfiPODkzSxxop7D0rZ91L6ZuMlcMCSh0YyK+gAfo5zN/ih6WxMwhoXgJWC3cWQdaKC+A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.7.0", - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", - "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", - "dev": true - } - } - }, - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", - "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-index": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz", - "integrity": "sha1-7FanSe4QPk4Ix5C5w1PfFgVbl/k=", - "requires": { - "debug": "^2.2.0", - "es6-symbol": "^3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array.prototype.map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", - "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.4" - } - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "charm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/charm/-/charm-1.0.2.tgz", - "integrity": "sha1-it02cVOm2aWBMxBSxAkJkdqZXjU=", - "dev": true, - "requires": { - "inherits": "^2.0.1" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "clang-format": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.4.0.tgz", - "integrity": "sha512-NrdyUnHJOGvMa60vbWk7GJTvOdhibj3uK5C0FlwdNG4301OUvqEJTFce9I9x8qw2odBbIVrJ+9xbsFS3a4FbDA==", - "dev": true, - "requires": { - "async": "^1.5.2", - "glob": "^7.0.0", - "resolve": "^1.1.6" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "dev": true - }, - "commander": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", - "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==", - "dev": true - }, - "compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", - "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==" - }, - "dts-critic": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/dts-critic/-/dts-critic-3.3.2.tgz", - "integrity": "sha512-9rVXHAvZgdB63Au4Pile2QaPA2/2Ucuu5CsVd6MhIqFdOzjuZVnyR9cdJPgrW12mk/fSYQyMJ5b3Nuyq2ZUFoQ==", - "dev": true, - "requires": { - "@definitelytyped/header-parser": "^0.0.57", - "command-exists": "^1.2.8", - "rimraf": "^3.0.2", - "semver": "^6.2.0", - "tmp": "^0.2.1", - "yargs": "^15.3.1" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "dtslint": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/dtslint/-/dtslint-4.0.4.tgz", - "integrity": "sha512-z5+aPNcF9gRjMLH95bMPsm1AYHERo3O6wFRf+2W1qRn/0b7xh4Qs1g+i0x/Th0Z3XRIIrhrBcW3dkvXgsQ95wA==", - "dev": true, - "requires": { - "@definitelytyped/header-parser": "^0.0.57", - "@definitelytyped/typescript-versions": "^0.0.57", - "@definitelytyped/utils": "^0.0.57", - "dts-critic": "^3.3.2", - "fs-extra": "^6.0.1", - "json-stable-stringify": "^1.0.1", - "strip-json-comments": "^2.0.1", - "tslint": "5.14.0", - "yargs": "^15.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", - "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", - "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", - "dev": true, - "requires": { - "es-abstract": "^1.17.4", - "has-symbols": "^1.0.1", - "is-arguments": "^1.0.4", - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz", - "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.1.3", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^1.3.0", - "espree": "^7.3.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "espree": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", - "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", - "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", - "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", - "dev": true, - "requires": { - "semver-regex": "^2.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "foreachasync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", - "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs-extra": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", - "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^1.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-from-current-process-h": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-from-current-process-h/-/get-symbol-from-current-process-h-1.0.2.tgz", - "integrity": "sha512-syloC6fsCt62ELLrr1VKBM1ggOpMdetX9hTrdW77UQdcApPHLmf7CI7OKcN1c9kYuNxKcDe4iJ4FY9sX3aw2xw==" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "globby": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", - "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "husky": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", - "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "int64-napi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/int64-napi/-/int64-napi-1.0.1.tgz", - "integrity": "sha512-UPprIixcZdhdLobpKgHm6/HJD9VIR53JE5Fx93nJzgnX10hCxUd8nzOukxL2WDmjT2SWfz/VzDvk6qfPBLnEVg==", - "requires": { - "bindings": "^1.3.0" - } - }, - "is-arguments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-close": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/is-close/-/is-close-1.3.3.tgz", - "integrity": "sha512-Q8pmIuDS2BUAj9NElFDxKNv11JXWqXNVa5+i3kjWmT0r2SVxVkXmBCexBuooPS4r59C5F3STMi5thXKP56/FIg==" - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", - "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-set": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", - "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", - "dev": true - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "iterate-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", - "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", - "dev": true - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "lint-staged": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.4.0.tgz", - "integrity": "sha512-uaiX4U5yERUSiIEQc329vhCTDDwUcSvKdRLsNomkYLRzijk3v8V9GWm2Nz0RMVB87VcuzLvtgy6OsjoH++QHIg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "cli-truncate": "^2.1.0", - "commander": "^6.0.0", - "cosmiconfig": "^7.0.0", - "debug": "^4.1.1", - "dedent": "^0.7.0", - "enquirer": "^2.3.6", - "execa": "^4.0.3", - "listr2": "^2.6.0", - "log-symbols": "^4.0.0", - "micromatch": "^4.0.2", - "normalize-path": "^3.0.0", - "please-upgrade-node": "^3.2.0", - "string-argv": "0.3.1", - "stringify-object": "^3.3.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "listr2": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.2.tgz", - "integrity": "sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "cli-truncate": "^2.1.0", - "figures": "^3.2.0", - "indent-string": "^4.0.0", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rxjs": "^6.6.2", - "through": "^2.3.8" - }, - "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "requires": { - "chalk": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mocha": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", - "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.2", - "debug": "4.1.1", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.0", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-package-arg": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", - "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", - "dev": true, - "requires": { - "hosted-git-info": "^2.7.1", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-registry-client": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.6.0.tgz", - "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", - "dev": true, - "requires": { - "concat-stream": "^1.5.2", - "graceful-fs": "^4.1.6", - "normalize-package-data": "~1.0.1 || ^2.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", - "npmlog": "2 || ^3.1.0 || ^4.0.0", - "once": "^1.3.3", - "request": "^2.74.0", - "retry": "^0.10.0", - "safe-buffer": "^5.1.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5", - "slide": "^1.1.3", - "ssri": "^5.2.4" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-is": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", - "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parsimmon": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.16.0.tgz", - "integrity": "sha512-tekGDz2Lny27SQ/5DzJdIK0lqsWwZ667SCLFIDCxaZM7VNgQjyKLbaL7FYPKpbjdxNAXFV/mSxkq5D2fnkW4pA==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "requires": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "ref-array-di": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ref-array-di/-/ref-array-di-1.2.2.tgz", - "integrity": "sha512-jhCmhqWa7kvCVrWhR/d7RemkppqPUdxEil1CtTtm7FkZV8LcHHCK3Or9GinUiFP5WY3k0djUkMvhBhx49Jb2iA==", - "requires": { - "array-index": "^1.0.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "ref-napi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ref-napi/-/ref-napi-3.0.1.tgz", - "integrity": "sha512-W3rcb0E+tlO9u9ySFnX5vifInwwPGToOfFgTZUHJBNiOBsW0NNvgHz2zJN7ctABo/2yIlgdPQUvuqqfORIF4LA==", - "requires": { - "debug": "^4.1.1", - "get-symbol-from-current-process-h": "^1.0.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.1" - } - }, - "ref-struct-di": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ref-struct-di/-/ref-struct-di-1.1.1.tgz", - "integrity": "sha512-2Xyn/0Qgz89VT+++WP0sTosdm9oeowLP23wRJYhG4BFdMUrLj3jhwHZNEytYNYgtPKLNTP3KJX4HEgBvM1/Y2g==", - "requires": { - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", - "dev": true - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true - }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", - "dev": true - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "sinon": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.3.tgz", - "integrity": "sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.2", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.1.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } - } - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tslint": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz", - "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", - "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", - "dev": true - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" - }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "walk": { - "version": "2.3.14", - "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.14.tgz", - "integrity": "sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg==", - "requires": { - "foreachasync": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", - "dev": true - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yaml": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", - "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "yargs-parser": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", - "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - } - } -} From 355fb02c6da32cc3441344cda421a24e5d4b30af Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 10:31:49 +0800 Subject: [PATCH 08/64] link to correct library --- rosidl_gen/idl_generator.js | 12 ++++++------ rosidl_gen/templates/typesupportGypi.dot | 8 +++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 72b60b21..24567bbd 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -425,7 +425,7 @@ async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { } /** - * Tries to guess the libraries needed to be linked against for typesupport_c. + * Tries to guess the libraries needed to be linked against for generator_c. * * Normally, the typesupport libraries are built at compiled time of the message packages. The * libraries that have to be linked against are based on the name of the cmake target. Because @@ -438,9 +438,9 @@ async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { * * @param {string} pkg name of the package * @param {string} amentRoot ament root directory - * @returns {string[]} an array of typesupport_c libraries found + * @returns {string[]} an array of generator_c libraries found */ -async function guessTypesupportCLibs(pkg, amentRoot) { +async function guessGeneratorCLibs(pkg, amentRoot) { const cmakeExport = await fs.readFile( path.join( amentRoot, @@ -455,12 +455,12 @@ async function guessTypesupportCLibs(pkg, amentRoot) { /set\s*\(\s*(?:_exported_typesupport_libraries|_exported_libraries)\s*"(.*)"/ ); if (!match || match.length < 2) { - throw new Error(`unable to find typesupport library for ${pkg}`); + throw new Error(`unable to find generator_c library for ${pkg}`); } const libraries = match[1].replace(/:/g, ';'); const typesupportCLibs = []; libraries.split(';').forEach((lib) => { - if (lib.endsWith('rosidl_typesupport_c')) { + if (lib.endsWith('rosidl_generator_c')) { typesupportCLibs.push(lib); } }); @@ -472,7 +472,7 @@ async function generateTypesupportGypi(pkgsEntries) { pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ pkgName, pkgInfo, - typesupportLibs: await guessTypesupportCLibs(pkgName, pkgInfo.amentRoot), + typesupportLibs: await guessGeneratorCLibs(pkgName, pkgInfo.amentRoot), })) ); const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); diff --git a/rosidl_gen/templates/typesupportGypi.dot b/rosidl_gen/templates/typesupportGypi.dot index 217ae5e9..23e2b8f7 100644 --- a/rosidl_gen/templates/typesupportGypi.dot +++ b/rosidl_gen/templates/typesupportGypi.dot @@ -6,11 +6,13 @@ 'sources': [ '{{=pkg.pkgName}}/definitions.cpp', ], - 'libraries': [ + 'link_settings': { + 'libraries': [ {{~ pkg.typesupportLibs : lib}} - '-l{{=lib}}', + '-l{{=lib}}', {{~}} - ], + ], + }, }, {{~}} ], From 47a162708fb520082242895d1979616b7330ba4d Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 10:32:08 +0800 Subject: [PATCH 09/64] remove test.js --- test.js | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 test.js diff --git a/test.js b/test.js deleted file mode 100644 index 6eab8d38..00000000 --- a/test.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -const rclnodejs = require('.'); -const test = require('bindings')('std_msgs'); -console.log(test.String.create()); - -// rclnodejs.init().then(() => { -// const node = rclnodejs.createNode('test'); -// node.createSubscription('std_msgs/msg/String', 'test', (msg) => { -// console.log(msg); -// }); -// rclnodejs.spin(node); -// }); From 8085c7f6c1fed2a1c2394258615e99365cc8cfa1 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 11:17:04 +0800 Subject: [PATCH 10/64] export as class --- lib/interface_loader.js | 3 ++- rosidl_gen/templates/cppDefinitions.dot | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/interface_loader.js b/lib/interface_loader.js index 70b8e923..1ddfb0b8 100644 --- a/lib/interface_loader.js +++ b/lib/interface_loader.js @@ -17,6 +17,7 @@ const path = require('path'); const fs = require('fs'); const generator = require('../rosidl_gen/index.js'); +const bindings = require('bindings'); let interfaceLoader = { loadInterfaceByObject(obj) { @@ -110,7 +111,7 @@ let interfaceLoader = { ); // eslint-disable-next-line if (fs.existsSync(filePath)) { - return require(filePath); + return bindings(packageName)[messageName]; } } throw new Error( diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index f7bff807..f95526bc 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -21,11 +21,12 @@ namespace rclnodejs { {{~ it.messages : message}} NAN_MODULE_INIT(rclnodejs__{{=message.structType}}::Init) { - auto obj = Nan::New(); - obj->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); - obj->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); - obj->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); - Nan::Set(target, Nan::New("{{=message.info.interfaceName}}").ToLocalChecked(), obj); + auto clazz = Nan::New(); + clazz->SetClassName(Nan::New("{{=message.interfaceName}}").ToLocalChecked()); + clazz->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); + clazz->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); + clazz->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); + Nan::Set(target, Nan::New("{{=message.info.interfaceName}}").ToLocalChecked(), Nan::GetFunction(clazz).ToLocalChecked()); } void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsObj, {{=message.structType}}* msg) { From 7fd4799aa31df1f156694755efe3afc3f72cdd6f Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 11:25:08 +0800 Subject: [PATCH 11/64] remove usage of deprecated functions --- rosidl_gen/templates/cppDefinitions.dot | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index f95526bc..36af7f24 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -34,7 +34,7 @@ void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsOb {{? !it.isInternalField(field)}} { // end with underscore so it doesn't conflicts with field names - auto js_value_ = jsObj->Get(Nan::New("{{=field.name}}").ToLocalChecked()); + auto js_value_ = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); {{ const jsType = it.getJsType(field.type); }} @@ -79,9 +79,9 @@ v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=messag {{? !it.isInternalField(field)}} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - jsObj->Set(Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); + Nan::Set(jsObj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); {{??}} - jsObj->Set(Nan::New("{{=field.name}}").ToLocalChecked(), rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::MakeJsObject(&msg->{{=field.name}})); + Nan::Set(jsObj,Nan::New("{{=field.name}}").ToLocalChecked(), rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::MakeJsObject(&msg->{{=field.name}})); {{?}} {{??}} // TODO: handle array From 8c5d83342f05c70d53280240dabaeffe2e11ecc6 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 7 Dec 2020 11:52:33 +0800 Subject: [PATCH 12/64] it works! --- lib/interface_loader.js | 3 +-- lib/node.js | 6 +++--- lib/subscription.js | 6 +++++- rosidl_gen/templates/message.dot | 13 +++++++++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/interface_loader.js b/lib/interface_loader.js index 1ddfb0b8..70b8e923 100644 --- a/lib/interface_loader.js +++ b/lib/interface_loader.js @@ -17,7 +17,6 @@ const path = require('path'); const fs = require('fs'); const generator = require('../rosidl_gen/index.js'); -const bindings = require('bindings'); let interfaceLoader = { loadInterfaceByObject(obj) { @@ -111,7 +110,7 @@ let interfaceLoader = { ); // eslint-disable-next-line if (fs.existsSync(filePath)) { - return bindings(packageName)[messageName]; + return require(filePath); } } throw new Error( diff --git a/lib/node.js b/lib/node.js index 7daf0717..40b0ce5d 100644 --- a/lib/node.js +++ b/lib/node.js @@ -1520,9 +1520,9 @@ class Node { * @returns {undefined} */ _runWithMessageType(Type, callback) { - if (process.env.RCLNODEJS_USE_ROS_SERIALIZATION) { - let message = Type.create(); - callback(message, () => Type.ToJsObject(message)); + if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { + let message = Type.createRosMessage(); + callback(message, () => Type.rosMessageToObj(message)); } else { let message = new Type(); diff --git a/lib/subscription.js b/lib/subscription.js index 96a7f261..0fce3749 100644 --- a/lib/subscription.js +++ b/lib/subscription.js @@ -36,7 +36,11 @@ class Subscription extends Entity { if (this._isRaw) { this._callback(msg); } else { - this._callback(msg.toPlainObject(this.typedArrayEnabled)); + if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { + this._callback(msg); + } else { + this._callback(msg.toPlainObject(this.typedArrayEnabled)); + } } } diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index a6943adf..e36e1ae8 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -225,6 +225,7 @@ const ArrayType = require('ref-array-di')(ref); const primitiveTypes = require('../../rosidl_gen/primitive_types.js'); const deallocator = require('../../rosidl_gen/deallocator.js'); const translator = require('../../rosidl_gen/message_translator.js'); +const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}').{{=it.messageInfo.interfaceName}}; {{~ it.spec.fields :field}} {{? shouldRequire(it.spec.baseType, field.type)}} @@ -356,6 +357,18 @@ class {{=objectWrapper}} { return {{=refObjectType}}; } + static createRosMessage() { + return typesupport.create(); + } + + static rosMessageToObj(rosMsg) { + return typesupport.to(rosMsg); + } + + static rosMessageFromObj(obj) { + return typesupport.from(obj); + } + toRawROS() { this.freeze(true); return this._refObject.ref(); From 4e017aecc9f6c37d490fe8d198f6182192fbff8d Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 8 Dec 2020 11:17:15 +0800 Subject: [PATCH 13/64] support publishing --- lib/node.js | 2 +- rosidl_gen/idl_generator.js | 187 +++++++++++------- rosidl_gen/index.js | 2 +- rosidl_gen/templates/cppDefinitions.dot | 132 +++++++------ rosidl_gen/templates/cppDefinitionsHeader.dot | 15 +- rosidl_gen/templates/message.dot | 22 ++- rosidl_gen/templates/typesupportGypi.dot | 4 +- 7 files changed, 213 insertions(+), 151 deletions(-) diff --git a/lib/node.js b/lib/node.js index 40b0ce5d..88c0b410 100644 --- a/lib/node.js +++ b/lib/node.js @@ -1522,7 +1522,7 @@ class Node { _runWithMessageType(Type, callback) { if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { let message = Type.createRosMessage(); - callback(message, () => Type.rosMessageToObj(message)); + callback(message, () => Type.toJsObject(message)); } else { let message = new Type(); diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 24567bbd..d8f23dfc 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -26,21 +26,59 @@ class RosIdlDb { this.pkgIndex = pkgs; this.specIndex = {}; this.messageInfoIndex = {}; + this.dependentMessagesIndex = {}; this.dependentPackagesIndex = {}; + this.linkLibrariesIndex = {}; for (let pkg of pkgs.values()) { pkg.messages.forEach((messageInfo) => { - this.messageInfoIndex[ - `${messageInfo.pkgName}__${messageInfo.interfaceName}` - ] = messageInfo; + this.messageInfoIndex[this._messageInfoHash(messageInfo)] = messageInfo; }); } } + setSpec(messageInfo, spec) { + this.specIndex[this._messageInfoHash(messageInfo)] = spec; + } + getMessageInfoFromType(type) { - return this.messageInfoIndex[`${type.pkgName}__${type.type}`]; + return this.messageInfoIndex[`${type.pkgName}/${type.type}`]; + } + + /** + * Gets a list of all messages that a message depends on. + * @param {string} messageInfo Base message. + * @returns {object[]} An array of message infos. + */ + async getDependentMessages(messageInfo) { + const key = this._messageInfoHash(messageInfo); + let dependentMessages = this.dependentMessagesIndex[key]; + if (dependentMessages === undefined) { + this.dependentMessagesIndex[key] = new Promise(async (res) => { + const set = new Set(); + const spec = await this.getMessageSpec(messageInfo); + spec.fields.forEach((field) => { + if ( + field.type.pkgName && + field.type.pkgName !== messageInfo.pkgName + ) { + // `this.getMessageInfoFromType` must always return the + // same object for the same type for this to work + set.add(this.getMessageInfoFromType(field.type)); + } + }); + res(Array.from(set.values())); + }); + return this.dependentMessagesIndex[key]; + } + return dependentMessages; } - async getDependentMessages(pkgName) { + /** + * Gets a list of packages that a given package depends on. + * @param {string} pkgName Name of the base package + * @returns {Promise} An array containing name of all dependent packages. + */ + async getDependentPackages(pkgName) { let dependentPackages = this.dependentPackagesIndex[pkgName]; if (dependentPackages === undefined) { this.dependentPackagesIndex[pkgName] = new Promise(async (res) => { @@ -50,9 +88,7 @@ class RosIdlDb { const spec = await this.getMessageSpec(messageInfo); spec.fields.forEach((field) => { if (field.type.pkgName && field.type.pkgName !== pkgName) { - // `this.getMessageInfoFromType` must always return the - // same object for the same type for this to work - set.add(this.getMessageInfoFromType(field.type)); + set.add(field.type.pkgName); } }); } @@ -64,7 +100,7 @@ class RosIdlDb { } _messageInfoHash(messageInfo) { - return `${messageInfo.pkgName}__${messageInfo.interfaceName}`; + return `${messageInfo.pkgName}/${messageInfo.interfaceName}`; } async getMessageSpec(messageInfo) { @@ -84,13 +120,72 @@ class RosIdlDb { return promise; } - // _getDependentPackagesImpl(pkg) + async getLinkLibraries(pkgName) { + let linkLibraries = this.linkLibrariesIndex[pkgName]; + if (linkLibraries === undefined) { + this.linkLibrariesIndex[pkgName] = new Promise(async (res) => { + const set = new Set(); + const dependentPackages = await this.getDependentPackages(pkgName); + const dependentLibraries = ( + await Promise.all( + dependentPackages.map((name) => this.getLinkLibraries(name)) + ) + ).flat(); + dependentLibraries.forEach((lib) => set.add(lib)); + + const pkg = this.pkgIndex.get(pkgName); + const generatorCLibs = await this._guessGeneratorCLibs(pkg); + generatorCLibs.forEach((lib) => set.add(lib)); - // getDependentPackages(pkg) { - // pkg.messages.forEach((messageInfo) => { + res(Array.from(set.values())); + }); + linkLibraries = this.linkLibrariesIndex[pkgName]; + } + return linkLibraries; + } - // }) - // } + /** + * Tries to guess the libraries needed to be linked against for generator_c. + * + * Normally, the typesupport libraries are built at compiled time of the message packages. The + * libraries that have to be linked against are based on the name of the cmake target. Because + * + * 1. We are a third party library, so our typesupport cannot be built at the compile time. + * 2. We are use node-gyp as the build tool, so we can't use cmake to find the link libraries. + * + * The stopgap solution is then to use regexp on the cmake config files to try to find the + * required link libraries. + * + * @param {string} pkg package info + * @param {string} amentRoot ament root directory + * @returns {Promise} an array of generator_c libraries found + */ + async _guessGeneratorCLibs(pkg) { + const cmakeExport = await fs.readFile( + path.join( + pkg.amentRoot, + 'share', + pkg.pkgName, + 'cmake', + 'ament_cmake_export_libraries-extras.cmake' + ), + 'utf-8' + ); + const match = cmakeExport.match( + /set\s*\(\s*(?:_exported_typesupport_libraries|_exported_libraries)\s*"(.*)"/ + ); + if (!match || match.length < 2) { + throw new Error(`unable to find generator_c library for ${pkg}`); + } + const libraries = match[1].replace(/:/g, ';'); + const generatorCLibs = []; + libraries.split(';').forEach((lib) => { + if (lib.endsWith('rosidl_generator_c')) { + generatorCLibs.push(lib); + } + }); + return generatorCLibs; + } } dot.templateSettings.strip = false; @@ -140,7 +235,7 @@ async function generateMessageJSStruct(messageInfo, dir, rosIdlDb) { await generateMessageJSStructFromSpec(messageInfo, dir, spec); } -function generateMessageJSStructFromSpec(messageInfo, dir, spec) { +async function generateMessageJSStructFromSpec(messageInfo, dir, spec) { dir = path.join(dir, `${spec.baseType.pkgName}`); const fileName = spec.baseType.pkgName + @@ -187,6 +282,10 @@ function getJsType(rosType) { return 'object'; } +function isInternalField(field) { + return field.name.startsWith('_'); +} + function isServiceMessage(messageInfo) { return ( messageInfo.interfaceName.endsWith('_Request') || @@ -194,10 +293,6 @@ function isServiceMessage(messageInfo) { ); } -function isInternalField(field) { - return field.name.startsWith('_'); -} - // All messages are combined in one cpp file to improve compile time. async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { const getStructType = (messageInfo) => { @@ -222,14 +317,14 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { } } - const dependentMessages = await rosIdlDb.getDependentMessages(pkgName); + const dependentPackages = await rosIdlDb.getDependentPackages(pkgName); const source = removeEmptyLines( dots.cppDefinitions({ pkgName, pkgInfo, messages, - dependentMessages, + dependentPackages, rosIdlDb, getStructType, getRosHeaderField, @@ -244,7 +339,7 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { pkgName, pkgInfo, messages, - dependentMessages, + dependentPackages, rosIdlDb, getStructType, getRosHeaderField, @@ -424,55 +519,13 @@ async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { ]); } -/** - * Tries to guess the libraries needed to be linked against for generator_c. - * - * Normally, the typesupport libraries are built at compiled time of the message packages. The - * libraries that have to be linked against are based on the name of the cmake target. Because - * - * 1. We are a third party library, so our typesupport cannot be built at the compile time. - * 2. We are use node-gyp as the build tool, so we can't use cmake to find the link libraries. - * - * The stopgap solution is then to use regexp on the cmake config files to try to find the - * required link libraries. - * - * @param {string} pkg name of the package - * @param {string} amentRoot ament root directory - * @returns {string[]} an array of generator_c libraries found - */ -async function guessGeneratorCLibs(pkg, amentRoot) { - const cmakeExport = await fs.readFile( - path.join( - amentRoot, - 'share', - pkg, - 'cmake', - 'ament_cmake_export_libraries-extras.cmake' - ), - 'utf-8' - ); - const match = cmakeExport.match( - /set\s*\(\s*(?:_exported_typesupport_libraries|_exported_libraries)\s*"(.*)"/ - ); - if (!match || match.length < 2) { - throw new Error(`unable to find generator_c library for ${pkg}`); - } - const libraries = match[1].replace(/:/g, ';'); - const typesupportCLibs = []; - libraries.split(';').forEach((lib) => { - if (lib.endsWith('rosidl_generator_c')) { - typesupportCLibs.push(lib); - } - }); - return typesupportCLibs; -} - -async function generateTypesupportGypi(pkgsEntries) { +async function generateTypesupportGypi(pkgsEntries, rosIdlDb) { const pkgs = await Promise.all( pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ pkgName, pkgInfo, - typesupportLibs: await guessGeneratorCLibs(pkgName, pkgInfo.amentRoot), + linkLibraries: await rosIdlDb.getLinkLibraries(pkgName), + dependencies: await rosIdlDb.getDependentPackages(pkgName), })) ); const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 1c3dfec1..112a6403 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -55,7 +55,7 @@ async function generateInPaths(paths) { generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) ) ); - await generateTypesupportGypi(pkgsEntries); + await generateTypesupportGypi(pkgsEntries, rosIdlDb); } async function generateAll(forcedGenerating) { diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 36af7f24..d94683d8 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -6,64 +6,90 @@ #include "definitions.hpp" #include "../../type_conversion.hpp" -{{~ it.dependentMessages : messageInfo}} -#include "../{{=messageInfo.pkgName}}/definitions.hpp" -{{~}} - {{~ it.messages : message}} #include <{{=it.getRosHeaderField(message.info)}}> {{~}} -{{~ it.dependentMessages : messageInfo}} -struct {{=it.getStructType(messageInfo)}}; -{{~}} namespace rclnodejs { {{~ it.messages : message}} NAN_MODULE_INIT(rclnodejs__{{=message.structType}}::Init) { auto clazz = Nan::New(); - clazz->SetClassName(Nan::New("{{=message.interfaceName}}").ToLocalChecked()); - clazz->Set(Nan::New("create").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::Create)); - clazz->Set(Nan::New("from").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::FromJsObject)); - clazz->Set(Nan::New("to").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); + clazz->SetClassName(Nan::New("{{=message.info.interfaceName}}").ToLocalChecked()); + clazz->Set(Nan::New("createRosMessage").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::CreateRosMessage)); + clazz->Set(Nan::New("writeRosMessage").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::WriteRosMessage)); + clazz->Set(Nan::New("toJsObject").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); Nan::Set(target, Nan::New("{{=message.info.interfaceName}}").ToLocalChecked(), Nan::GetFunction(clazz).ToLocalChecked()); } -void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsObj, {{=message.structType}}* msg) { +NAN_METHOD(rclnodejs__{{=message.structType}}::CreateRosMessage) { + auto* data = {{=message.structType}}__create(); + auto buffer = Nan::NewBuffer(reinterpret_cast(data), sizeof(*data), [](auto* data, auto) { + {{=message.structType}}__destroy(reinterpret_cast<{{=message.structType}}*>(data)); + }, nullptr).ToLocalChecked(); + info.GetReturnValue().Set(buffer); +} + +NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { + auto jsObj = Nan::To(info[0]).ToLocalChecked(); + auto* buffer = node::Buffer::Data(info[1]); + auto offset = Nan::To(info[2]).ToChecked(); + auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); + auto typesupport = Nan::To(info[3]).ToLocalChecked(); + {{~ message.spec.fields : field}} {{? !it.isInternalField(field)}} { - // end with underscore so it doesn't conflicts with field names - auto js_value_ = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); {{ const jsType = it.getJsType(field.type); }} {{? jsType === 'number'}} - if (!js_value_->IsNumber()) { - throw new std::runtime_error("expected {{=field.name}} to be number"); + if (!js_value->IsNumber()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be number").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; } {{?? jsType === 'string'}} - if (!js_value_->IsString()) { - throw new std::runtime_error("expected {{=field.name}} to be string"); + if (!js_value->IsString()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be string").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; } {{?? jsType === 'boolean'}} - if (!js_value_->IsBoolean()) { - throw new std::runtime_error("expected {{=field.name}} to be boolean"); + if (!js_value->IsBoolean()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be boolean").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; } {{?? jsType === 'bigint'}} - if (!js_value_->IsBigInt()) { - throw new std::runtime_error("expected {{=field.name}} to be bigint"); + if (!js_value->IsBigInt()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be bigint").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; } {{??}} - if (!js_value_->IsObject()) { - throw new std::runtime_error("expected {{=field.name}} to be {{=field.type.type}} object"); + if (!js_value->IsObject()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be {{=field.type.type}} object").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; } {{?}} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value_); + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} - rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::WriteMessage(Nan::To(js_value_).ToLocalChecked(), &msg->{{=field.name}}); + { + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto {{=field.name}}_jsObj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + {{=field.name}}_jsObj, + info[1], + Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) + }; + Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); + } {{?}} {{??}} // TODO: handle array types @@ -71,9 +97,16 @@ void rclnodejs__{{=message.structType}}::WriteMessage(v8::Local jsOb } {{?}} {{~}} + + info.GetReturnValue().Set(Nan::Undefined()); } -v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=message.structType}}* msg) { +NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { + auto* buffer = node::Buffer::Data(info[0]); + uint32_t offset = Nan::To(info[1]).ToChecked(); + auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); + auto typesupport = Nan::To(info[2]).ToLocalChecked(); + auto jsObj = Nan::New(); {{~ message.spec.fields : field}} {{? !it.isInternalField(field)}} @@ -81,46 +114,23 @@ v8::Local rclnodejs__{{=message.structType}}::MakeJsObject({{=messag {{? field.type.isPrimitiveType}} Nan::Set(jsObj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); {{??}} - Nan::Set(jsObj,Nan::New("{{=field.name}}").ToLocalChecked(), rclnodejs__{{=it.getStructTypeFromRosType(field.type)}}::MakeJsObject(&msg->{{=field.name}})); + { + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("toJsObject").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + info[0], + Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) + }; + auto {{=field.name}}_jsObj = Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); + Nan::Set(jsObj, Nan::New("{{=field.name}}").ToLocalChecked(), {{=field.name}}_jsObj); + } {{?}} {{??}} // TODO: handle array {{?}} {{?}} {{~}} - return jsObj; -} - -NAN_METHOD(rclnodejs__{{=message.structType}}::Create) { - auto* data = {{=message.structType}}__create(); - auto buffer = Nan::NewBuffer(reinterpret_cast(data), sizeof(*data), [](auto* data, auto) { - {{=message.structType}}__destroy(reinterpret_cast<{{=message.structType}}*>(data)); - }, nullptr).ToLocalChecked(); - info.GetReturnValue().Set(buffer); -} - -NAN_METHOD(rclnodejs__{{=message.structType}}::FromJsObject) { - auto jsObj = Nan::To(info[0]).ToLocalChecked(); - auto* msg = {{=message.structType}}__create(); - - try { - rclnodejs__{{=message.structType}}::WriteMessage(jsObj, msg); - } catch (const std::runtime_error& e) { - Nan::ThrowError(Nan::New(e.what()).ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - - auto buffer = Nan::NewBuffer(reinterpret_cast(msg), sizeof(*msg), [](auto* msg, auto) { - {{=message.structType}}__destroy(reinterpret_cast<{{=message.structType}}*>(msg)); - }, nullptr).ToLocalChecked(); - info.GetReturnValue().Set(buffer); -} - -NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { - auto* buffer = node::Buffer::Data(info[0]); - auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer); - info.GetReturnValue().Set(rclnodejs__{{=message.structType}}::MakeJsObject(msg)); + info.GetReturnValue().Set(jsObj); } {{~}} diff --git a/rosidl_gen/templates/cppDefinitionsHeader.dot b/rosidl_gen/templates/cppDefinitionsHeader.dot index b6585174..aa500a3e 100644 --- a/rosidl_gen/templates/cppDefinitionsHeader.dot +++ b/rosidl_gen/templates/cppDefinitionsHeader.dot @@ -8,10 +8,6 @@ #include -{{~ it.messages : message}} -struct {{=message.structType}}; -{{~}} - namespace rclnodejs { {{~ it.messages : message }} @@ -19,17 +15,10 @@ class rclnodejs__{{=message.structType}} { public: static NAN_MODULE_INIT(Init); - static void WriteMessage(v8::Local jsObj, {{=message.structType}}* msg); - - /** - * Must be called within a v8 scope - */ - static v8::Local MakeJsObject({{=message.structType}}* msg); - private: - static NAN_METHOD(Create); + static NAN_METHOD(CreateRosMessage); - static NAN_METHOD(FromJsObject); + static NAN_METHOD(WriteRosMessage); static NAN_METHOD(ToJsObject); }; diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index e36e1ae8..f99ef7ce 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -225,11 +225,15 @@ const ArrayType = require('ref-array-di')(ref); const primitiveTypes = require('../../rosidl_gen/primitive_types.js'); const deallocator = require('../../rosidl_gen/deallocator.js'); const translator = require('../../rosidl_gen/message_translator.js'); -const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}').{{=it.messageInfo.interfaceName}}; +const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; +const typesupportDeps = {}; {{~ it.spec.fields :field}} {{? shouldRequire(it.spec.baseType, field.type)}} const {{=getWrapperNameByType(field.type)}} = require('../../generated/{{=getPackageNameByType(field.type)}}/{{=getModulePathByType(field.type, it.messageInfo)}}'); +{{? field.type.pkgName}} +typesupportDeps['{{=field.type.pkgName}}/{{=field.type.type}}'] = {{=getWrapperNameByType(field.type)}}; +{{?}} {{?}} {{~}} @@ -358,15 +362,21 @@ class {{=objectWrapper}} { } static createRosMessage() { - return typesupport.create(); + return typesupport.createRosMessage(); + } + + static toJsObject(buffer, offset = 0) { + return typesupport.toJsObject(buffer, offset, typesupportDeps); } - static rosMessageToObj(rosMsg) { - return typesupport.to(rosMsg); + static toRosMessage(obj) { + const rosMessage = {{=objectWrapper}}.createRosMessage(); + {{=objectWrapper}}.writeRosMessage(obj, rosMessage, 0); + return rosMessage; } - static rosMessageFromObj(obj) { - return typesupport.from(obj); + static writeRosMessage(obj, buffer, offset) { + typesupport.writeRosMessage(obj, buffer, 0, typesupportDeps); } toRawROS() { diff --git a/rosidl_gen/templates/typesupportGypi.dot b/rosidl_gen/templates/typesupportGypi.dot index 23e2b8f7..0b732b9d 100644 --- a/rosidl_gen/templates/typesupportGypi.dot +++ b/rosidl_gen/templates/typesupportGypi.dot @@ -2,13 +2,13 @@ 'targets': [ {{~ it.pkgs : pkg}} { - 'target_name': '{{=pkg.pkgName}}', + 'target_name': '{{=pkg.pkgName}}__rosidl_node', 'sources': [ '{{=pkg.pkgName}}/definitions.cpp', ], 'link_settings': { 'libraries': [ -{{~ pkg.typesupportLibs : lib}} +{{~ pkg.linkLibraries : lib}} '-l{{=lib}}', {{~}} ], From ccc93704ea306ec776c7d885cf7d4a632b8441e5 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 8 Dec 2020 11:46:33 +0800 Subject: [PATCH 14/64] fix not using offset --- rosidl_gen/templates/message.dot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index f99ef7ce..fa6a3dbe 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -376,7 +376,7 @@ class {{=objectWrapper}} { } static writeRosMessage(obj, buffer, offset) { - typesupport.writeRosMessage(obj, buffer, 0, typesupportDeps); + typesupport.writeRosMessage(obj, buffer, offset, typesupportDeps); } toRawROS() { From 01685fea20183f9d9c594d49b55e097e0cd66162 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 8 Dec 2020 11:46:43 +0800 Subject: [PATCH 15/64] benchmark c struct conversion --- .../rclnodejs/message/c-struct-to-js-obj.js | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 benchmark/rclnodejs/message/c-struct-to-js-obj.js diff --git a/benchmark/rclnodejs/message/c-struct-to-js-obj.js b/benchmark/rclnodejs/message/c-struct-to-js-obj.js new file mode 100644 index 00000000..27bbe878 --- /dev/null +++ b/benchmark/rclnodejs/message/c-struct-to-js-obj.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * Benchmarks the performance in converting from native C struct to javascript objects. + * Requires the ros package "test_msgs" to be available. + */ +const app = require('commander'); + +app.option('-r, --runs ', 'Number of times to run').parse(process.argv); +const runs = app.runs || 1; + +const BasicTypes = require('../../../generated/test_msgs/test_msgs__msg__BasicTypes'); + +if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { + const rosMessage = BasicTypes.toRosMessage({ + bool_value: false, + byte_value: 0, + char_value: 0, + float32_value: 0, + float64_value: 0, + int8_value: 0, + uint8_value: 0, + int16_value: 0, + uint16_value: 0, + int32_value: 0, + uint32_value: 0, + int64_value: BigInt(0), + uint64_value: BigInt(0), + }); + const startTime = process.hrtime(); + for (let i = 0; i < runs; i++) { + BasicTypes.toJsObject(rosMessage); + } + const timeTaken = process.hrtime(startTime); + console.log( + `Benchmark took ${timeTaken[0]} seconds and ${Math.ceil( + timeTaken[1] / 1000000 + )} milliseconds.` + ); +} else { + const msg = new BasicTypes({ + bool_value: false, + byte_value: 0, + char_value: 0, + float32_value: 0, + float64_value: 0, + int8_value: 0, + uint8_value: 0, + int16_value: 0, + uint16_value: 0, + int32_value: 0, + uint32_value: 0, + int64_value: 0, + uint64_value: 0, + }); + msg.freeze(); + const rawMessage = msg._refObject; + const startTime = process.hrtime(); + for (let i = 0; i < runs; i++) { + msg.deserialize(rawMessage); + } + const timeTaken = process.hrtime(startTime); + console.log( + `Benchmark took ${timeTaken[0]} seconds and ${Math.ceil( + timeTaken[1] / 1000000 + )} milliseconds.` + ); +} From d6e5a6612222c53e14bed140cde254dcfd7028e8 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 8 Dec 2020 12:17:46 +0800 Subject: [PATCH 16/64] conditionally use rosidl provider at compile time --- lib/node.js | 3 +- lib/subscription.js | 3 +- rosidl_gen/idl_generator.js | 63 +++++++++++++++++++++++--------- rosidl_gen/index.js | 22 +++++++---- rosidl_gen/templates/message.dot | 6 ++- 5 files changed, 69 insertions(+), 28 deletions(-) diff --git a/lib/node.js b/lib/node.js index 88c0b410..38331017 100644 --- a/lib/node.js +++ b/lib/node.js @@ -37,6 +37,7 @@ const Service = require('./service.js'); const Subscription = require('./subscription.js'); const TimeSource = require('./time_source.js'); const Timer = require('./timer.js'); +const generateOptions = require('../generated/generator-options'); // Parameter event publisher constants const PARAMETER_EVENT_MSG_TYPE = 'rcl_interfaces/msg/ParameterEvent'; @@ -1520,7 +1521,7 @@ class Node { * @returns {undefined} */ _runWithMessageType(Type, callback) { - if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { + if (generatorOptions.idlProvider === 'rosidl') { let message = Type.createRosMessage(); callback(message, () => Type.toJsObject(message)); } else { diff --git a/lib/subscription.js b/lib/subscription.js index 0fce3749..b78594cd 100644 --- a/lib/subscription.js +++ b/lib/subscription.js @@ -17,6 +17,7 @@ const rclnodejs = require('bindings')('rclnodejs'); const Entity = require('./entity.js'); const debug = require('debug')('rclnodejs:subscription'); +const generatorOptions = require('../generated/generator-options'); /** * @class - Class representing a Subscription in ROS @@ -36,7 +37,7 @@ class Subscription extends Entity { if (this._isRaw) { this._callback(msg); } else { - if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { + if (generatorOptions.idlProvider === 'rosidl') { this._callback(msg); } else { this._callback(msg.toPlainObject(this.typedArrayEnabled)); diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index d8f23dfc..b3830e73 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -230,12 +230,17 @@ function generateServiceJSStruct(serviceInfo, dir) { return writeGeneratedCode(dir, fileName, generatedCode); } -async function generateMessageJSStruct(messageInfo, dir, rosIdlDb) { +async function generateMessageJSStruct(messageInfo, dir, rosIdlDb, options) { const spec = await rosIdlDb.getMessageSpec(messageInfo); - await generateMessageJSStructFromSpec(messageInfo, dir, spec); + await generateMessageJSStructFromSpec(messageInfo, dir, spec, options); } -async function generateMessageJSStructFromSpec(messageInfo, dir, spec) { +async function generateMessageJSStructFromSpec( + messageInfo, + dir, + spec, + options +) { dir = path.join(dir, `${spec.baseType.pkgName}`); const fileName = spec.baseType.pkgName + @@ -250,6 +255,7 @@ async function generateMessageJSStructFromSpec(messageInfo, dir, spec) { messageInfo: messageInfo, spec: spec, json: JSON.stringify(spec, null, ' '), + options, }) ); return writeGeneratedCode(dir, fileName, generatedCode); @@ -294,7 +300,11 @@ function isServiceMessage(messageInfo) { } // All messages are combined in one cpp file to improve compile time. -async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { +async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { + if (options.idlProvider !== 'rosidl') { + return; + } + const getStructType = (messageInfo) => { return `${messageInfo.pkgName}__${messageInfo.subFolder}__${messageInfo.interfaceName}`; }; @@ -355,7 +365,7 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) { await fs.writeFile(path.join(outputDir, 'definitions.hpp'), header); } -async function generateActionJSStruct(actionInfo, dir) { +async function generateActionJSStruct(actionInfo, dir, options) { const spec = await parser.parseActionFile( actionInfo.pkgName, actionInfo.filePath @@ -368,7 +378,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_Goal`, }, dir, - spec.goal + spec.goal, + options ); const resultMsg = generateMessageJSStructFromSpec( @@ -378,7 +389,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_Result`, }, dir, - spec.result + spec.result, + options ); const feedbackMsg = generateMessageJSStructFromSpec( @@ -388,7 +400,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_Feedback`, }, dir, - spec.feedback + spec.feedback, + options ); const sendGoalRequestSpec = actionMsgs.createSendGoalRequestSpec( @@ -402,7 +415,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_SendGoal_Request`, }, dir, - sendGoalRequestSpec + sendGoalRequestSpec, + options ); const sendGoalResponseSpec = actionMsgs.createSendGoalResponseSpec( @@ -416,7 +430,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_SendGoal_Response`, }, dir, - sendGoalResponseSpec + sendGoalResponseSpec, + options ); const sendGoalSrv = generateServiceJSStruct( @@ -439,7 +454,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_GetResult_Request`, }, dir, - getResultRequestSpec + getResultRequestSpec, + options ); const getResultResponseSpec = actionMsgs.createGetResultResponseSpec( @@ -453,7 +469,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_GetResult_Response`, }, dir, - getResultResponseSpec + getResultResponseSpec, + options ); const getResultSrv = generateServiceJSStruct( @@ -476,7 +493,8 @@ async function generateActionJSStruct(actionInfo, dir) { interfaceName: `${actionInfo.interfaceName}_FeedbackMessage`, }, dir, - feedbackMessageSpec + feedbackMessageSpec, + options ); const fileName = @@ -507,19 +525,30 @@ async function generateActionJSStruct(actionInfo, dir) { ]); } -async function generateJSStructFromIDL(pkg, dir, rosIdlDb) { +async function generateJSStructFromIDL(pkg, dir, rosIdlDb, options) { await Promise.all([ ...pkg.messages.map((messageInfo) => - generateMessageJSStruct(messageInfo, dir, rosIdlDb) + generateMessageJSStruct(messageInfo, dir, rosIdlDb, options) ), ...pkg.services.map((serviceInfo) => generateServiceJSStruct(serviceInfo, dir) ), - ...pkg.actions.map((actionInfo) => generateActionJSStruct(actionInfo, dir)), + ...pkg.actions.map((actionInfo) => + generateActionJSStruct(actionInfo, dir, options) + ), ]); } -async function generateTypesupportGypi(pkgsEntries, rosIdlDb) { +async function generateTypesupportGypi(pkgsEntries, rosIdlDb, options) { + await fs.mkdir(path.join('src', 'generated'), { recursive: true }); + if (options.idlProvider !== 'rosidl') { + await fs.writeFile( + path.join('src', 'generated', 'typesupport.gypi'), + '# not using rosidl\n{}' + ); + return; + } + const pkgs = await Promise.all( pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ pkgName, diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 112a6403..625095aa 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -14,6 +14,7 @@ 'use strict'; +const fsp = require('fs').promises; const fse = require('fs-extra'); const { RosIdlDb, @@ -29,7 +30,7 @@ const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split( path.delimiter ); -async function generateInPaths(paths) { +async function generateInPaths(paths, options) { const pkgsInPaths = await Promise.all( paths.map((path) => packages.findPackagesInDirectory(path)) ); @@ -47,15 +48,16 @@ async function generateInPaths(paths) { await Promise.all( pkgsInfo.map((pkgInfo) => - generateJSStructFromIDL(pkgInfo, generatedRoot, rosIdlDb) + generateJSStructFromIDL(pkgInfo, generatedRoot, rosIdlDb, options) ) ); + await Promise.all( pkgsEntries.map(([pkgName, pkgInfo]) => - generateCppDefinitions(pkgName, pkgInfo, rosIdlDb) + generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) ) ); - await generateTypesupportGypi(pkgsEntries, rosIdlDb); + await generateTypesupportGypi(pkgsEntries, rosIdlDb, options); } async function generateAll(forcedGenerating) { @@ -68,10 +70,14 @@ async function generateAll(forcedGenerating) { path.join(__dirname, 'generator.json'), path.join(generatedRoot, 'generator.json') ); - await generateInPaths(installedPackagePaths); - // await Promise.all( - // installedPackagePaths.map((path) => generateInPath(path)) - // ); + const options = { + idlProvider: process.env.RCLNODEJS_USE_ROSIDL ? 'rosidl' : 'ref', + }; + await generateInPaths(installedPackagePaths, options); + await fsp.writeFile( + path.join(generatedRoot, 'generator-options.js'), + `module.export = ${JSON.stringify(options)}` + ); } } diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index fa6a3dbe..4f86d91f 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -225,13 +225,15 @@ const ArrayType = require('ref-array-di')(ref); const primitiveTypes = require('../../rosidl_gen/primitive_types.js'); const deallocator = require('../../rosidl_gen/deallocator.js'); const translator = require('../../rosidl_gen/message_translator.js'); +{{? it.options.idlProvider === 'rosidl'}} const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; +{{?}} const typesupportDeps = {}; {{~ it.spec.fields :field}} {{? shouldRequire(it.spec.baseType, field.type)}} const {{=getWrapperNameByType(field.type)}} = require('../../generated/{{=getPackageNameByType(field.type)}}/{{=getModulePathByType(field.type, it.messageInfo)}}'); -{{? field.type.pkgName}} +{{? it.options.idlProvider === 'rosidl' && field.type.pkgName}} typesupportDeps['{{=field.type.pkgName}}/{{=field.type.type}}'] = {{=getWrapperNameByType(field.type)}}; {{?}} {{?}} @@ -361,6 +363,7 @@ class {{=objectWrapper}} { return {{=refObjectType}}; } +{{? it.options.idlProvider === 'rosidl'}} static createRosMessage() { return typesupport.createRosMessage(); } @@ -378,6 +381,7 @@ class {{=objectWrapper}} { static writeRosMessage(obj, buffer, offset) { typesupport.writeRosMessage(obj, buffer, offset, typesupportDeps); } +{{?}} toRawROS() { this.freeze(true); From 74d2dcb1e5bb5fe7255ebcc320b698d9f9206528 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 8 Dec 2020 12:21:41 +0800 Subject: [PATCH 17/64] use parallel build --- package.json | 2 +- scripts/build.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 scripts/build.js diff --git a/package.json b/package.json index a9b87e73..e332cd6a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "typescript" ], "scripts": { - "install": "node scripts/generate_messages.js && node-gyp rebuild", + "install": "node scripts/generate_messages.js && node scripts/build.js", "docs": "cd docs && make", "test": "node ./scripts/compile_tests.js && node --expose-gc ./scripts/run_test.js && npm run dtslint", "dtslint": "node ./scripts/generate_tsd.js && dtslint test/types", diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 00000000..9254ed15 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,7 @@ +const childprocess = require('child_process'); +const os = require('os'); + +process.env.JOBS = os.cpus().length; +childprocess.execSync('node-gyp rebuild', { + stdio: 'inherit', +}); From c8fcbcc8bde5be2ca0fabf2e928b6a36cddfea75 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 9 Dec 2020 09:43:16 +0800 Subject: [PATCH 18/64] fix strings --- lib/publisher.js | 26 ++++++++++++++++---------- rosidl_gen/index.js | 8 ++++++-- src/type_conversion.hpp | 1 + 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/publisher.js b/lib/publisher.js index 7342c3c1..c34ef03b 100644 --- a/lib/publisher.js +++ b/lib/publisher.js @@ -17,6 +17,7 @@ const rclnodejs = require('bindings')('rclnodejs'); const debug = require('debug')('rclnodejs:publisher'); const Entity = require('./entity.js'); +const generatorOptions = require('../generated/generator-options'); /** * @class - Class representing a Publisher in ROS @@ -46,17 +47,22 @@ class Publisher extends Entity { if (message instanceof Buffer) { rclnodejs.publishRawMessage(this._handle, message); } else { - // Enables call by plain object/number/string argument - // e.g. publisher.publish(3.14); - // publisher.publish('The quick brown fox...'); - // publisher.publish({linear: {x: 0, y: 1, z: 2}, ...}); - let messageToSend = - message instanceof this._typeClass - ? message - : new this._typeClass(message); + if (generatorOptions.idlProvider === 'rosidl') { + let rawMessage = this._typeClass.toRosMessage(message); + rclnodejs.publish(this._handle, rawMessage); + } else { + // Enables call by plain object/number/string argument + // e.g. publisher.publish(3.14); + // publisher.publish('The quick brown fox...'); + // publisher.publish({linear: {x: 0, y: 1, z: 2}, ...}); + let messageToSend = + message instanceof this._typeClass + ? message + : new this._typeClass(message); - let rawMessage = messageToSend.serialize(); - rclnodejs.publish(this._handle, rawMessage); + let rawMessage = messageToSend.serialize(); + rclnodejs.publish(this._handle, rawMessage); + } } debug(`Message of topic ${this.topic} has been published.`); diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 625095aa..8cc53241 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -71,12 +71,16 @@ async function generateAll(forcedGenerating) { path.join(generatedRoot, 'generator.json') ); const options = { - idlProvider: process.env.RCLNODEJS_USE_ROSIDL ? 'rosidl' : 'ref', + idlProvider: + process.env.RCLNODEJS_USE_ROSIDL && + process.env.RCLNODEJS_USE_ROSIDL !== '0' + ? 'rosidl' + : 'ref', }; await generateInPaths(installedPackagePaths, options); await fsp.writeFile( path.join(generatedRoot, 'generator-options.js'), - `module.export = ${JSON.stringify(options)}` + `module.exports = ${JSON.stringify(options)}` ); } } diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 3f58fe58..289e949e 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -59,6 +59,7 @@ inline rosidl_runtime_c__String ToNativeChecked( throw std::runtime_error("failed to convert value to string"); } rosidl_runtime_c__String ros_string; + rosidl_runtime_c__String__init(&ros_string); rosidl_runtime_c__String__assign(&ros_string, *utf8); return ros_string; } From 750f1c84f2b2f6026c5a523fcd504a6782e16e96 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 9 Dec 2020 18:50:31 +0800 Subject: [PATCH 19/64] add js to c benchmark --- .../rclnodejs/message/c-struct-to-js-obj.js | 3 +- .../rclnodejs/message/js-obj-to-c-struct.js | 68 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 benchmark/rclnodejs/message/js-obj-to-c-struct.js diff --git a/benchmark/rclnodejs/message/c-struct-to-js-obj.js b/benchmark/rclnodejs/message/c-struct-to-js-obj.js index 27bbe878..3477006f 100644 --- a/benchmark/rclnodejs/message/c-struct-to-js-obj.js +++ b/benchmark/rclnodejs/message/c-struct-to-js-obj.js @@ -5,13 +5,14 @@ * Requires the ros package "test_msgs" to be available. */ const app = require('commander'); +const generatorOptions = require('../../../generated/generator-options'); app.option('-r, --runs ', 'Number of times to run').parse(process.argv); const runs = app.runs || 1; const BasicTypes = require('../../../generated/test_msgs/test_msgs__msg__BasicTypes'); -if (process.env.RCLNODEJS_USE_ROS_MESSAGE) { +if (generatorOptions.idlProvider === 'rosidl') { const rosMessage = BasicTypes.toRosMessage({ bool_value: false, byte_value: 0, diff --git a/benchmark/rclnodejs/message/js-obj-to-c-struct.js b/benchmark/rclnodejs/message/js-obj-to-c-struct.js new file mode 100644 index 00000000..f7c77398 --- /dev/null +++ b/benchmark/rclnodejs/message/js-obj-to-c-struct.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * Benchmarks the performance in converting from to javascript objects to native C structs. + * Requires the ros package "test_msgs" to be available. + */ +const app = require('commander'); +const generatorOptions = require('../../../generated/generator-options'); + +app.option('-r, --runs ', 'Number of times to run').parse(process.argv); +const runs = app.runs || 1; + +const BasicTypes = require('../../../generated/test_msgs/test_msgs__msg__BasicTypes'); + +if (generatorOptions.idlProvider === 'rosidl') { + const jsObj = { + bool_value: false, + byte_value: 0, + char_value: 0, + float32_value: 0, + float64_value: 0, + int8_value: 0, + uint8_value: 0, + int16_value: 0, + uint16_value: 0, + int32_value: 0, + uint32_value: 0, + int64_value: BigInt(0), + uint64_value: BigInt(0), + }; + const startTime = process.hrtime(); + for (let i = 0; i < runs; i++) { + BasicTypes.toRosMessage(jsObj); + } + const timeTaken = process.hrtime(startTime); + console.log( + `Benchmark took ${timeTaken[0]} seconds and ${Math.ceil( + timeTaken[1] / 1000000 + )} milliseconds.` + ); +} else { + const jsObj = { + bool_value: false, + byte_value: 0, + char_value: 0, + float32_value: 0, + float64_value: 0, + int8_value: 0, + uint8_value: 0, + int16_value: 0, + uint16_value: 0, + int32_value: 0, + uint32_value: 0, + int64_value: 0, + uint64_value: 0, + }; + const startTime = process.hrtime(); + for (let i = 0; i < runs; i++) { + const msg = new BasicTypes(jsObj); + msg.serialize(); + } + const timeTaken = process.hrtime(startTime); + console.log( + `Benchmark took ${timeTaken[0]} seconds and ${Math.ceil( + timeTaken[1] / 1000000 + )} milliseconds.` + ); +} From a413620abc6fe031b13d80c3539329f7e1393bae Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 12:12:00 +0800 Subject: [PATCH 20/64] update benchmark with no zerocopy mode --- benchmark/rclnodejs/message/c-struct-to-js-obj.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/benchmark/rclnodejs/message/c-struct-to-js-obj.js b/benchmark/rclnodejs/message/c-struct-to-js-obj.js index 3477006f..3c82b8ec 100644 --- a/benchmark/rclnodejs/message/c-struct-to-js-obj.js +++ b/benchmark/rclnodejs/message/c-struct-to-js-obj.js @@ -56,9 +56,12 @@ if (generatorOptions.idlProvider === 'rosidl') { }); msg.freeze(); const rawMessage = msg._refObject; + const deserializeFunc = process.env.RCLNODEJS_NO_ZEROCOPY + ? (rawMessage) => msg.toPlainObject(msg.deserialize(rawMessage)) + : (rawMessage) => msg.deserialize(rawMessage); const startTime = process.hrtime(); for (let i = 0; i < runs; i++) { - msg.deserialize(rawMessage); + deserializeFunc(rawMessage); } const timeTaken = process.hrtime(startTime); console.log( From 5a29f193c49827d3768490bc98607fe8e4842d27 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 14:52:30 +0800 Subject: [PATCH 21/64] more strict type checking --- rosidl_gen/templates/cppDefinitions.dot | 57 +++++++++- src/type_conversion.hpp | 142 ++++++++++++++++++++---- 2 files changed, 176 insertions(+), 23 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index d94683d8..5b84bfdc 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -10,6 +10,8 @@ #include <{{=it.getRosHeaderField(message.info)}}> {{~}} +#include + namespace rclnodejs { {{~ it.messages : message}} @@ -44,6 +46,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{ const jsType = it.getJsType(field.type); }} +{{? !field.type.isArray}} {{? jsType === 'number'}} if (!js_value->IsNumber()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be number").ToLocalChecked()); @@ -75,9 +78,14 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { return; } {{?}} -{{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); + try { + msg->{{=field.name}} = ToNative{{=field.name}})>(js_value); + } catch (TypeError e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; + } {{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -92,7 +100,50 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { } {{?}} {{??}} - // TODO: handle array types +{{? field.type.isPrimitiveTypeasd}} + if (!js_value->IsArray()) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to be an array").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; + } + auto js_array = js_value.As(); +{{? field.type.isFixedSizeArray}} + if (js_array->Length() != {{=field.type.arraySize}}) { + Nan::ThrowError(Nan::New("expected {{=field.name}} to have length {{=field.type.arraySize}}").ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; + } + + for (uint32_t i = 0; i < {{=field.type.arraySize}}; ++i) { +{{? field.type.type === 'string'}} + try { + msg->{{=field.name}}[i] = ToNative(Nan::Get(js_array, i).ToLocalChecked()); + } catch (TypeError e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + info.GetReturnValue().Set(Nan::Undefined()); + return; + } + } +{{??}} + msg->{{=field.name}}[i] = ToNative{{=field.name}})>>(Nan::Get(js_array, i).ToLocalChecked()); +{{?}} + } +{{??}} + // TODO: handle sequences +{{?}} +{{??}} + { + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}__Sequence").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto {{=field.name}}_jsObj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + {{=field.name}}_jsObj, + info[1], + Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) + }; + Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); + } +{{?}} {{?}} } {{?}} diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 289e949e..c111b348 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -7,53 +7,155 @@ #include #include +#include +#include +#include +#include +#include + namespace rclnodejs { +class TypeError : public std::exception { + public: + explicit TypeError(const std::vector& expected_types) { + std::ostringstream oss; + for (size_t i = 0; i < expected_types.size() - 1; ++i) { + oss << expected_types[i] << " or "; + } + oss << expected_types[expected_types.size() - 1]; + _expected_types = oss.str(); + _what = "expected " + _expected_types; + } + + const char* what() const noexcept override { return _what.c_str(); } + + std::string what_detailed(const std::string& field_name) { + return "expected \"" + field_name + "\" to be " + _expected_types; + } + + private: + std::string _expected_types; + std::string _what; +}; + template -inline T ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline T ToNative(v8::Local val); + +template <> +inline int8_t ToNative(v8::Local val) { + int32_t native; + if (!Nan::To(std::move(val)).To(&native) || + native > std::numeric_limits::max() || + native < std::numeric_limits::min()) { + throw TypeError({"int8"}); + } + return static_cast(native); } template <> -inline int8_t ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline uint8_t ToNative(v8::Local val) { + uint32_t native; + if (!Nan::To(std::move(val)).To(&native) || + native > std::numeric_limits::max() || + native < std::numeric_limits::min()) { + throw TypeError({"uint8"}); + } + return static_cast(native); } template <> -inline uint8_t ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline int16_t ToNative(v8::Local val) { + int32_t native; + if (!Nan::To(std::move(val)).To(&native) || + native > std::numeric_limits::max() || + native < std::numeric_limits::min()) { + throw TypeError({"int16"}); + } + return static_cast(native); } template <> -inline int16_t ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline uint16_t ToNative(v8::Local val) { + uint32_t native; + if (!Nan::To(std::move(val)).To(&native) || + native > std::numeric_limits::max() || + native < std::numeric_limits::min()) { + throw TypeError({"uint16"}); + } + return static_cast(native); } template <> -inline uint16_t ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline int32_t ToNative(v8::Local val) { + int32_t native; + if (!Nan::To(std::move(val)).To(&native)) { + throw TypeError({"int32"}); + } + return native; } template <> -inline int64_t ToNativeChecked(v8::Local val) { - return val->ToBigInt(Nan::GetCurrentContext()).ToLocalChecked()->Int64Value(); +inline uint32_t ToNative(v8::Local val) { + uint32_t native; + if (!Nan::To(std::move(val)).To(&native)) { + throw TypeError({"uint32"}); + } + return native; } template <> -inline uint64_t ToNativeChecked(v8::Local val) { - return val->ToBigInt(Nan::GetCurrentContext()) - .ToLocalChecked() - ->Uint64Value(); +inline int64_t ToNative(v8::Local val) { + v8::Local bigint; + if (!val->ToBigInt(Nan::GetCurrentContext()).ToLocal(&bigint)) { + throw TypeError({"int64"}); + } + return bigint->Int64Value(); +} + +template <> +inline uint64_t ToNative(v8::Local val) { + v8::Local bigint; + if (!val->ToBigInt(Nan::GetCurrentContext()).ToLocal(&bigint)) { + throw TypeError({"unt64"}); + } + return bigint->Uint64Value(); +} + +template <> +inline float ToNative(v8::Local val) { + double native; + if (!Nan::To(std::move(val)).To(&native) || + native > std::numeric_limits::max() || + native < std::numeric_limits::min()) { + throw TypeError({"float"}); + } + return static_cast(native); } template <> -inline float ToNativeChecked(v8::Local val) { - return Nan::To(std::move(val)).ToChecked(); +inline double ToNative(v8::Local val) { + double native; + if (!Nan::To(std::move(val)).To(&native)) { + throw TypeError({"double"}); + } + return native; +} + +template <> +inline bool ToNative(v8::Local val) { + bool native; + if (!Nan::To(std::move(val)).To(&native)) { + throw TypeError({"bool"}); + } + return native; } template <> -inline rosidl_runtime_c__String ToNativeChecked( +inline rosidl_runtime_c__String ToNative( v8::Local val) { + if (!val->IsString()) { + throw TypeError({"string"}); + }; Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); @@ -65,7 +167,7 @@ inline rosidl_runtime_c__String ToNativeChecked( } template <> -inline rosidl_runtime_c__U16String ToNativeChecked( +inline rosidl_runtime_c__U16String ToNative( v8::Local val) { // TODO: throw std::runtime_error("not implemented"); From 7966b96fcdefc7cdfbd61b700f57dfd594c963f4 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 14:59:01 +0800 Subject: [PATCH 22/64] u16string conversion --- src/type_conversion.hpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index c111b348..5ce464a1 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -7,8 +7,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -38,6 +40,16 @@ class TypeError : public std::exception { std::string _what; }; +std::u16string string_to_u16string(const std::string& input) { + std::wstring_convert, char16_t> converter; + return converter.from_bytes(input); +} + +std::string u16string_to_string(const std::u16string& input) { + std::wstring_convert, char16_t> converter; + return converter.to_bytes(input); +} + template inline T ToNative(v8::Local val); @@ -169,8 +181,19 @@ inline rosidl_runtime_c__String ToNative( template <> inline rosidl_runtime_c__U16String ToNative( v8::Local val) { - // TODO: - throw std::runtime_error("not implemented"); + if (!val->IsString()) { + throw TypeError({"string"}); + }; + Nan::Utf8String utf8(val); + if (*utf8 == nullptr) { + throw std::runtime_error("failed to convert value to string"); + } + auto u16s = string_to_u16string(*utf8); + rosidl_runtime_c__U16String ros_string; + rosidl_runtime_c__U16String__init(&ros_string); + rosidl_runtime_c__U16String__assign( + &ros_string, reinterpret_cast(u16s.c_str())); + return ros_string; } template From de17d58e126a24f09b6b8fdd8f4d3d82fa473a02 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 16:28:10 +0800 Subject: [PATCH 23/64] Revert "more strict type checking" This reverts commit 5a29f193c49827d3768490bc98607fe8e4842d27. --- rosidl_gen/templates/cppDefinitions.dot | 57 +----------- src/type_conversion.hpp | 113 +++++------------------- 2 files changed, 23 insertions(+), 147 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 5b84bfdc..d94683d8 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -10,8 +10,6 @@ #include <{{=it.getRosHeaderField(message.info)}}> {{~}} -#include - namespace rclnodejs { {{~ it.messages : message}} @@ -46,7 +44,6 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{ const jsType = it.getJsType(field.type); }} -{{? !field.type.isArray}} {{? jsType === 'number'}} if (!js_value->IsNumber()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be number").ToLocalChecked()); @@ -78,14 +75,9 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { return; } {{?}} +{{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - try { - msg->{{=field.name}} = ToNative{{=field.name}})>(js_value); - } catch (TypeError e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -100,50 +92,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { } {{?}} {{??}} -{{? field.type.isPrimitiveTypeasd}} - if (!js_value->IsArray()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be an array").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - auto js_array = js_value.As(); -{{? field.type.isFixedSizeArray}} - if (js_array->Length() != {{=field.type.arraySize}}) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to have length {{=field.type.arraySize}}").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - - for (uint32_t i = 0; i < {{=field.type.arraySize}}; ++i) { -{{? field.type.type === 'string'}} - try { - msg->{{=field.name}}[i] = ToNative(Nan::Get(js_array, i).ToLocalChecked()); - } catch (TypeError e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - } -{{??}} - msg->{{=field.name}}[i] = ToNative{{=field.name}})>>(Nan::Get(js_array, i).ToLocalChecked()); -{{?}} - } -{{??}} - // TODO: handle sequences -{{?}} -{{??}} - { - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}__Sequence").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto {{=field.name}}_jsObj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); - v8::Local argv[] = { - {{=field.name}}_jsObj, - info[1], - Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) - }; - Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); - } -{{?}} + // TODO: handle array types {{?}} } {{?}} diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 5ce464a1..64548a90 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -51,123 +51,50 @@ std::string u16string_to_string(const std::u16string& input) { } template -inline T ToNative(v8::Local val); - -template <> -inline int8_t ToNative(v8::Local val) { - int32_t native; - if (!Nan::To(std::move(val)).To(&native) || - native > std::numeric_limits::max() || - native < std::numeric_limits::min()) { - throw TypeError({"int8"}); - } - return static_cast(native); +inline T ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline uint8_t ToNative(v8::Local val) { - uint32_t native; - if (!Nan::To(std::move(val)).To(&native) || - native > std::numeric_limits::max() || - native < std::numeric_limits::min()) { - throw TypeError({"uint8"}); - } - return static_cast(native); +inline int8_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline int16_t ToNative(v8::Local val) { - int32_t native; - if (!Nan::To(std::move(val)).To(&native) || - native > std::numeric_limits::max() || - native < std::numeric_limits::min()) { - throw TypeError({"int16"}); - } - return static_cast(native); +inline uint8_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline uint16_t ToNative(v8::Local val) { - uint32_t native; - if (!Nan::To(std::move(val)).To(&native) || - native > std::numeric_limits::max() || - native < std::numeric_limits::min()) { - throw TypeError({"uint16"}); - } - return static_cast(native); +inline int16_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline int32_t ToNative(v8::Local val) { - int32_t native; - if (!Nan::To(std::move(val)).To(&native)) { - throw TypeError({"int32"}); - } - return native; +inline uint16_t ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline uint32_t ToNative(v8::Local val) { - uint32_t native; - if (!Nan::To(std::move(val)).To(&native)) { - throw TypeError({"uint32"}); - } - return native; +inline int64_t ToNativeChecked(v8::Local val) { + return val->ToBigInt(Nan::GetCurrentContext()).ToLocalChecked()->Int64Value(); } template <> -inline int64_t ToNative(v8::Local val) { - v8::Local bigint; - if (!val->ToBigInt(Nan::GetCurrentContext()).ToLocal(&bigint)) { - throw TypeError({"int64"}); - } - return bigint->Int64Value(); +inline uint64_t ToNativeChecked(v8::Local val) { + return val->ToBigInt(Nan::GetCurrentContext()) + .ToLocalChecked() + ->Uint64Value(); } template <> -inline uint64_t ToNative(v8::Local val) { - v8::Local bigint; - if (!val->ToBigInt(Nan::GetCurrentContext()).ToLocal(&bigint)) { - throw TypeError({"unt64"}); - } - return bigint->Uint64Value(); +inline float ToNativeChecked(v8::Local val) { + return Nan::To(std::move(val)).ToChecked(); } template <> -inline float ToNative(v8::Local val) { - double native; - if (!Nan::To(std::move(val)).To(&native) || - native > std::numeric_limits::max() || - native < std::numeric_limits::min()) { - throw TypeError({"float"}); - } - return static_cast(native); -} - -template <> -inline double ToNative(v8::Local val) { - double native; - if (!Nan::To(std::move(val)).To(&native)) { - throw TypeError({"double"}); - } - return native; -} - -template <> -inline bool ToNative(v8::Local val) { - bool native; - if (!Nan::To(std::move(val)).To(&native)) { - throw TypeError({"bool"}); - } - return native; -} - -template <> -inline rosidl_runtime_c__String ToNative( +inline rosidl_runtime_c__String ToNativeChecked( v8::Local val) { - if (!val->IsString()) { - throw TypeError({"string"}); - }; Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); @@ -179,7 +106,7 @@ inline rosidl_runtime_c__String ToNative( } template <> -inline rosidl_runtime_c__U16String ToNative( +inline rosidl_runtime_c__U16String ToNativeChecked( v8::Local val) { if (!val->IsString()) { throw TypeError({"string"}); From 297fccc0ff0af1a1fb7d499b973974303f52d680 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 16:45:37 +0800 Subject: [PATCH 24/64] write array --- src/type_conversion.hpp | 228 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 64548a90..9ff77fef 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -40,6 +40,24 @@ class TypeError : public std::exception { std::string _what; }; +class OutOfRangeError : public std::exception { + public: + explicit OutOfRangeError(size_t len) : _len(len) { + _what = "expected array to have length " + len; + } + + const char* what() const noexcept override { return _what.c_str(); } + + std::string what_detailed(const std::string& field_name) { + return "expected \"" + field_name + "\" to have length " + + std::to_string(_len); + } + + private: + std::string _what; + size_t _len; +}; + std::u16string string_to_u16string(const std::string& input) { std::wstring_convert, char16_t> converter; return converter.from_bytes(input); @@ -123,6 +141,216 @@ inline rosidl_runtime_c__U16String ToNativeChecked( return ros_string; } +template +struct TypedArrayName {}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Int8Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Uint8Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Int16Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Uint16Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Int32Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "Uint32Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "BigInt64Array"; +}; + +template <> +struct TypedArrayName { + static constexpr const char* Name = "BigUint64Array"; +}; + +template +inline bool IsTypedArray(v8::Local val); + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsInt8Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsUint8Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsInt16Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsUint16Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsInt32Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsUint32Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsBigInt64Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsBigUint64Array(); +} + +template +inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, + size_t len) { + if (!IsTypedArray(val)) { + if (!val->IsArray()) { + throw TypeError({"array", TypedArrayName::Name}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + for (uint32_t i = 0; i < len; ++i) { + auto native = + ToNativeChecked(Nan::Get(array, i).ToLocalChecked()); + arr[i] = native; + } + } else { + auto typed_array = val.As(); + if (typed_array->Length() < len) { + throw OutOfRangeError(len); + } + typed_array->CopyContents(arr, len * sizeof(NativeT)); + } +} + +template +inline void WriteNativeArray(v8::Local val, T* arr, size_t len); + +template <> +inline void WriteNativeArray(v8::Local val, int8_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, uint8_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, int16_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, uint16_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, int32_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, uint32_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, int64_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, uint64_t* arr, + size_t len) { + WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, bool* arr, + size_t len) { + if (!val->IsArray()) { + throw TypeError({"array"}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + for (size_t i = 0; i < len; ++i) { + auto item = Nan::Get(array, i).ToLocalChecked(); + arr[i] = Nan::To(std::move(item)).ToChecked(); + } +} + +template <> +inline void WriteNativeArray(v8::Local val, float* arr, + size_t len) { + if (!val->IsArray()) { + throw TypeError({"array"}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + for (size_t i = 0; i < len; ++i) { + auto item = Nan::Get(array, i).ToLocalChecked(); + arr[i] = static_cast(Nan::To(std::move(item)).ToChecked()); + } +} + +template <> +inline void WriteNativeArray(v8::Local val, double* arr, + size_t len) { + if (!val->IsArray()) { + throw TypeError({"array"}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + for (size_t i = 0; i < len; ++i) { + auto item = Nan::Get(array, i).ToLocalChecked(); + arr[i] = Nan::To(std::move(item)).ToChecked(); + } +} + template inline v8::Local ToJsChecked(T val) { return Nan::New(val); From ed57bedd4cb6abee618b399b9b4eb7f23e18be29 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 17:23:16 +0800 Subject: [PATCH 25/64] primitive fixed size arrays --- rosidl_gen/templates/cppDefinitions.dot | 44 +++++++++++++++---------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index d94683d8..609a5348 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -37,48 +37,48 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); auto typesupport = Nan::To(info[3]).ToLocalChecked(); -{{~ message.spec.fields : field}} -{{? !it.isInternalField(field)}} + {{~ message.spec.fields : field}} + {{? !it.isInternalField(field)}} { auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); -{{ + {{ const jsType = it.getJsType(field.type); -}} -{{? jsType === 'number'}} + }} + {{? !field.type.isArray}} + {{? jsType === 'number'}} if (!js_value->IsNumber()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be number").ToLocalChecked()); info.GetReturnValue().Set(Nan::Undefined()); return; } -{{?? jsType === 'string'}} + {{?? jsType === 'string'}} if (!js_value->IsString()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be string").ToLocalChecked()); info.GetReturnValue().Set(Nan::Undefined()); return; } -{{?? jsType === 'boolean'}} + {{?? jsType === 'boolean'}} if (!js_value->IsBoolean()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be boolean").ToLocalChecked()); info.GetReturnValue().Set(Nan::Undefined()); return; } -{{?? jsType === 'bigint'}} + {{?? jsType === 'bigint'}} if (!js_value->IsBigInt()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be bigint").ToLocalChecked()); info.GetReturnValue().Set(Nan::Undefined()); return; } -{{??}} + {{??}} if (!js_value->IsObject()) { Nan::ThrowError(Nan::New("expected {{=field.name}} to be {{=field.type.type}} object").ToLocalChecked()); info.GetReturnValue().Set(Nan::Undefined()); return; } -{{?}} -{{? !field.type.isArray}} -{{? field.type.isPrimitiveType}} + {{?}} + {{? field.type.isPrimitiveType}} msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); -{{??}} + {{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -90,12 +90,20 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { }; Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); } -{{?}} -{{??}} - // TODO: handle array types -{{?}} + {{?}} + {{??}} + {{? field.type.isFixedSizeArray}} + {{? field.type.isPrimitiveType}} + WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); + {{??}} + // TODO: handle non-primitive arrays types + {{?}} + {{??}} + // TODO: handle sequences + {{?}} + {{?}} } -{{?}} + {{?}} {{~}} info.GetReturnValue().Set(Nan::Undefined()); From 6cd3df4f380a3670850298ead449cf2e4e9d88e1 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 17:30:55 +0800 Subject: [PATCH 26/64] skip type assertion, nan conversion it is generally safe, it will just return 0 or false if the type cannot be converted --- rosidl_gen/templates/cppDefinitions.dot | 31 ------------------------- 1 file changed, 31 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 609a5348..3011bcd8 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -45,37 +45,6 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { const jsType = it.getJsType(field.type); }} {{? !field.type.isArray}} - {{? jsType === 'number'}} - if (!js_value->IsNumber()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be number").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - {{?? jsType === 'string'}} - if (!js_value->IsString()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be string").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - {{?? jsType === 'boolean'}} - if (!js_value->IsBoolean()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be boolean").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - {{?? jsType === 'bigint'}} - if (!js_value->IsBigInt()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be bigint").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - {{??}} - if (!js_value->IsObject()) { - Nan::ThrowError(Nan::New("expected {{=field.name}} to be {{=field.type.type}} object").ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - return; - } - {{?}} {{? field.type.isPrimitiveType}} msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} From 37238de7aa179c69a1b232e0a8c1ca7dcb7f5758 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 10 Dec 2020 18:09:03 +0800 Subject: [PATCH 27/64] non-primitive fixed size arrays --- rosidl_gen/templates/cppDefinitions.dot | 23 ++++++++++++----------- src/type_conversion.hpp | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 3011bcd8..5f783bee 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -48,17 +48,15 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{? field.type.isPrimitiveType}} msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} - { - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto {{=field.name}}_jsObj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); - v8::Local argv[] = { - {{=field.name}}_jsObj, - info[1], - Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) - }; - Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); - } + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto {{=field.name}}_js_obj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + {{=field.name}}_js_obj, + info[1], + Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - reinterpret_cast(msg))) + }; + Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); {{?}} {{??}} {{? field.type.isFixedSizeArray}} @@ -66,6 +64,9 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); {{??}} // TODO: handle non-primitive arrays types + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_func); {{?}} {{??}} // TODO: handle sequences diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 9ff77fef..7798bd23 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -351,6 +351,31 @@ inline void WriteNativeArray(v8::Local val, double* arr, } } +template +inline void WriteNativeObjectArray(v8::Local val, T* arr, size_t len, + v8::Local node_buffer, + size_t offset, + v8::Local typesupport_func) { + if (!val->IsArray()) { + throw TypeError({"array"}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + auto msg_base = node::Buffer::Data(node_buffer) + offset; + v8::Local argv[] = {Nan::Undefined(), node_buffer, + Nan::Undefined()}; + for (size_t i = 0; i < len; ++i) { + auto item = Nan::Get(array, i).ToLocalChecked(); + argv[0] = item; + argv[2] = Nan::New( + static_cast(reinterpret_cast(&arr[i]) - msg_base)); + Nan::Call(typesupport_func, Nan::New(), 3, argv) + .ToLocalChecked(); + } +} + template inline v8::Local ToJsChecked(T val) { return Nan::New(val); From 7352bd9087e3e868ccf395f16e55f0afd1811669 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 11 Dec 2020 12:07:31 +0800 Subject: [PATCH 28/64] api compatible rosidl message --- lib/node.js | 20 +- lib/publisher.js | 26 +- lib/subscription.js | 7 +- rosidl_gen/idl_generator.js | 28 +- rosidl_gen/templates/cppDefinitions.dot | 4 +- rosidl_gen/templates/message.dot | 27 -- rosidl_gen/templates/messageRosidl.dot | 343 ++++++++++++++++++++++++ 7 files changed, 383 insertions(+), 72 deletions(-) create mode 100644 rosidl_gen/templates/messageRosidl.dot diff --git a/lib/node.js b/lib/node.js index 38331017..582fa5b3 100644 --- a/lib/node.js +++ b/lib/node.js @@ -37,7 +37,6 @@ const Service = require('./service.js'); const Subscription = require('./subscription.js'); const TimeSource = require('./time_source.js'); const Timer = require('./timer.js'); -const generateOptions = require('../generated/generator-options'); // Parameter event publisher constants const PARAMETER_EVENT_MSG_TYPE = 'rcl_interfaces/msg/ParameterEvent'; @@ -1521,21 +1520,16 @@ class Node { * @returns {undefined} */ _runWithMessageType(Type, callback) { - if (generatorOptions.idlProvider === 'rosidl') { - let message = Type.createRosMessage(); - callback(message, () => Type.toJsObject(message)); - } else { - let message = new Type(); + let message = new Type(); - callback(message.toRawROS(), () => { - let result = new Type(); - result.deserialize(message.refObject); + callback(message.toRawROS(), () => { + let result = new Type(); + result.deserialize(message.refObject); - return result; - }); + return result; + }); - Type.destoryRawROS(message); - } + Type.destoryRawROS(message); } _addActionClient(actionClient) { diff --git a/lib/publisher.js b/lib/publisher.js index c34ef03b..7342c3c1 100644 --- a/lib/publisher.js +++ b/lib/publisher.js @@ -17,7 +17,6 @@ const rclnodejs = require('bindings')('rclnodejs'); const debug = require('debug')('rclnodejs:publisher'); const Entity = require('./entity.js'); -const generatorOptions = require('../generated/generator-options'); /** * @class - Class representing a Publisher in ROS @@ -47,22 +46,17 @@ class Publisher extends Entity { if (message instanceof Buffer) { rclnodejs.publishRawMessage(this._handle, message); } else { - if (generatorOptions.idlProvider === 'rosidl') { - let rawMessage = this._typeClass.toRosMessage(message); - rclnodejs.publish(this._handle, rawMessage); - } else { - // Enables call by plain object/number/string argument - // e.g. publisher.publish(3.14); - // publisher.publish('The quick brown fox...'); - // publisher.publish({linear: {x: 0, y: 1, z: 2}, ...}); - let messageToSend = - message instanceof this._typeClass - ? message - : new this._typeClass(message); + // Enables call by plain object/number/string argument + // e.g. publisher.publish(3.14); + // publisher.publish('The quick brown fox...'); + // publisher.publish({linear: {x: 0, y: 1, z: 2}, ...}); + let messageToSend = + message instanceof this._typeClass + ? message + : new this._typeClass(message); - let rawMessage = messageToSend.serialize(); - rclnodejs.publish(this._handle, rawMessage); - } + let rawMessage = messageToSend.serialize(); + rclnodejs.publish(this._handle, rawMessage); } debug(`Message of topic ${this.topic} has been published.`); diff --git a/lib/subscription.js b/lib/subscription.js index b78594cd..96a7f261 100644 --- a/lib/subscription.js +++ b/lib/subscription.js @@ -17,7 +17,6 @@ const rclnodejs = require('bindings')('rclnodejs'); const Entity = require('./entity.js'); const debug = require('debug')('rclnodejs:subscription'); -const generatorOptions = require('../generated/generator-options'); /** * @class - Class representing a Subscription in ROS @@ -37,11 +36,7 @@ class Subscription extends Entity { if (this._isRaw) { this._callback(msg); } else { - if (generatorOptions.idlProvider === 'rosidl') { - this._callback(msg); - } else { - this._callback(msg.toPlainObject(this.typedArrayEnabled)); - } + this._callback(msg.toPlainObject(this.typedArrayEnabled)); } } diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index b3830e73..07388da1 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -250,14 +250,26 @@ async function generateMessageJSStructFromSpec( spec.msgName + '.js'; - const generatedCode = removeEmptyLines( - dots.message({ - messageInfo: messageInfo, - spec: spec, - json: JSON.stringify(spec, null, ' '), - options, - }) - ); + let generatedCode; + if (options.idlProvider === 'rosidl') { + generatedCode = removeEmptyLines( + dots.messageRosidl({ + messageInfo: messageInfo, + spec: spec, + json: JSON.stringify(spec, null, ' '), + options, + }) + ); + } else { + generatedCode = removeEmptyLines( + dots.message({ + messageInfo: messageInfo, + spec: spec, + json: JSON.stringify(spec, null, ' '), + options, + }) + ); + } return writeGeneratedCode(dir, fileName, generatedCode); } diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 5f783bee..35986864 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -49,7 +49,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto {{=field.name}}_js_obj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); v8::Local argv[] = { {{=field.name}}_js_obj, @@ -65,7 +65,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{??}} // TODO: handle non-primitive arrays types auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_func); {{?}} {{??}} diff --git a/rosidl_gen/templates/message.dot b/rosidl_gen/templates/message.dot index 4f86d91f..a6943adf 100644 --- a/rosidl_gen/templates/message.dot +++ b/rosidl_gen/templates/message.dot @@ -225,17 +225,10 @@ const ArrayType = require('ref-array-di')(ref); const primitiveTypes = require('../../rosidl_gen/primitive_types.js'); const deallocator = require('../../rosidl_gen/deallocator.js'); const translator = require('../../rosidl_gen/message_translator.js'); -{{? it.options.idlProvider === 'rosidl'}} -const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; -{{?}} -const typesupportDeps = {}; {{~ it.spec.fields :field}} {{? shouldRequire(it.spec.baseType, field.type)}} const {{=getWrapperNameByType(field.type)}} = require('../../generated/{{=getPackageNameByType(field.type)}}/{{=getModulePathByType(field.type, it.messageInfo)}}'); -{{? it.options.idlProvider === 'rosidl' && field.type.pkgName}} -typesupportDeps['{{=field.type.pkgName}}/{{=field.type.type}}'] = {{=getWrapperNameByType(field.type)}}; -{{?}} {{?}} {{~}} @@ -363,26 +356,6 @@ class {{=objectWrapper}} { return {{=refObjectType}}; } -{{? it.options.idlProvider === 'rosidl'}} - static createRosMessage() { - return typesupport.createRosMessage(); - } - - static toJsObject(buffer, offset = 0) { - return typesupport.toJsObject(buffer, offset, typesupportDeps); - } - - static toRosMessage(obj) { - const rosMessage = {{=objectWrapper}}.createRosMessage(); - {{=objectWrapper}}.writeRosMessage(obj, rosMessage, 0); - return rosMessage; - } - - static writeRosMessage(obj, buffer, offset) { - typesupport.writeRosMessage(obj, buffer, offset, typesupportDeps); - } -{{?}} - toRawROS() { this.freeze(true); return this._refObject.ref(); diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot new file mode 100644 index 00000000..c1243f03 --- /dev/null +++ b/rosidl_gen/templates/messageRosidl.dot @@ -0,0 +1,343 @@ +// This file is automatically generated by Intel rclnodejs +// +// *** DO NOT EDIT directly +// + +'use strict'; + +{{ +let objectWrapper = it.spec.msgName + 'Wrapper'; +let arrayWrapper = it.spec.msgName + 'ArrayWrapper'; + +let refObjectType = it.spec.msgName + 'RefStruct'; +let refObjectArrayType = it.spec.msgName + 'RefStructArray'; +let refArrayType = it.spec.msgName + 'RefArray'; +const compactMsgDefJSON = JSON.stringify(JSON.parse(it.json)); + +if (it.spec.fields.length === 0) { + it.spec.isEmpty = true; + /* Following rosidl_generator_c style, put a bool member named '_dummy' */ + it.spec.fields.push({ + "type": { + "isArray": false, + "pkgName": null, + "type": "bool", + "isDynamicArray": false, + "stringUpperBound": null, + "isUpperBound": false, + "isPrimitiveType": true, + "isFixedSizeArray": false, + "arraySize": null + }, + "name": "_dummy" + }); +} /* if */ + +function getPrimitiveNameByType(type) { + if (type.type === 'bool') { + return 'Bool'; + } else if (type.type === 'int8') { + return 'Int8'; + } else if (type.type === 'uint8') { + return 'UInt8'; + } else if (type.type === 'int16') { + return 'Int16'; + } else if (type.type === 'uint16') { + return 'UInt16'; + } else if (type.type === 'int32') { + return 'Int32'; + } else if (type.type === 'uint32') { + return 'UInt32'; + } else if (type.type === 'int64') { + return 'Int64'; + } else if (type.type === 'uint64') { + return 'UInt64'; + } else if (type.type === 'float64') { + return 'Float64'; + } else if (type.type === 'float32') { + return 'Float32'; + } else if (type.type === 'char') { + return 'Char'; + } else if (type.type === 'byte') { + return 'Byte'; + } else if (type.type === 'string' || type.type === 'wstring') { + return 'String'; + } else { + return ''; + } +} + +function getTypedArrayName(type) { + const t = type.type.toLowerCase(); + let typedArrayName; + + switch (t) { + case 'byte': + case 'octet': + case 'uint8': + typedArrayName = 'Uint8Array'; + break; + case 'char': + case 'int8': + typedArrayName = 'Int8Array'; + break; + case 'int16': + case 'short': + typedArrayName = 'Int16Array'; + break; + case 'uint16': + case 'unsigned short': + typedArrayName = 'Uint16Array'; + break; + case 'int32': + case 'long': + typedArrayName = 'Int32Array'; + break; + case 'uint32': + case 'unsigned long': + typedArrayName = 'Uint32Array'; + break; + case 'float': + case 'float32': + typedArrayName = 'Float32Array'; + break; + case 'double': + case 'float64': + typedArrayName = 'Float64Array'; + break; + default: + typedArrayName = ''; + } + + return typedArrayName; +} + +function getTypedArrayElementName(type) { + const t = type.type.toLowerCase(); + if (t === 'int8') { + return 'int8'; + } else if (t === 'uint8') { + return 'uint8'; + } else if (t === 'int16') { + return 'int16'; + } else if (t === 'uint16') { + return 'uint16'; + } else if (t === 'int32') { + return 'int32'; + } else if (t === 'uint32') { + return 'uint32'; + } else if (t === 'float64') { + return 'double'; + } else if (t === 'float32') { + return 'float'; + } else if (t === 'char') { + return 'int8'; + } else if (t === 'byte') { + return 'uint8'; + } else { + return ''; + } +} + +const primitiveBaseType = ['Bool', 'Int8', 'UInt8', 'Int16', 'UInt16', 'Int32', 'UInt32', + 'Int64', 'UInt64', 'Float64', 'Float32', 'Char', 'Byte', 'String']; +const typedArrayType = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', + 'float64', 'float32', 'char', 'byte']; + +let existedModules = []; + +function isExisted(requiredModule) { + return existedModules.indexOf(requiredModule) !== -1; +} + +function isPrimitivePackage(baseType) { + return primitiveBaseType.indexOf(baseType.type) !== -1; +} + +function isTypedArrayType(type) { + return typedArrayType.indexOf(type.type.toLowerCase()) !== -1; +} + +const usePlainTypedArray = isTypedArrayType(it.spec.baseType); +const currentTypedArray = getTypedArrayName(it.spec.baseType); +const currentTypedArrayElementType = getTypedArrayElementName(it.spec.baseType); + +function shouldRequire(baseType, fieldType) { + let requiredModule = '{{=getPackageNameByType(fieldType)}}/{{=getModulePathByType(fieldType)}}'; + let shouldRequire = !isPrimitivePackage(baseType) && (fieldType.isArray || !fieldType.isPrimitiveType || fieldType.type === 'string'); + + if (shouldRequire && !isExisted(requiredModule)) { + existedModules.push(requiredModule); + return true; + } else { + return false; + } +} + +function getWrapperNameByType(type) { + if (type.isPrimitiveType) { + return getPrimitiveNameByType(type) + 'Wrapper'; + } else { + return type.type + 'Wrapper'; + } +} + +function getModulePathByType(type, messageInfo) { + if (type.isPrimitiveType) { + return 'std_msgs__msg__' + getPrimitiveNameByType(type) + '.js'; + } + + if ( + messageInfo && + messageInfo.subFolder === 'action' && + messageInfo.pkgName === type.pkgName && + (type.type.endsWith('_Goal') || type.type.endsWith('_Result') || type.type.endsWith('_Feedback')) + ) { + return type.pkgName + '__action__' + type.type + '.js'; + } + + return type.pkgName + '__msg__' + type.type + '.js'; +} + +function getPackageNameByType(type) { + if (type.isPrimitiveType) { + return 'std_msgs'; + } else { + return type.pkgName; + } +} + +function extractMemberNames(fields) { + let memberNames = []; + fields.forEach(field => { + memberNames.push(field.name); + }); + return JSON.stringify(memberNames); +} +}} + +const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; + +const typesupportDeps = {}; +{{~ it.spec.fields :field}} + {{? shouldRequire(it.spec.baseType, field.type)}} +const {{=getWrapperNameByType(field.type)}} = require('../../generated/{{=getPackageNameByType(field.type)}}/{{=getModulePathByType(field.type, it.messageInfo)}}'); + {{? it.options.idlProvider === 'rosidl' && field.type.pkgName}} +typesupportDeps['{{=field.type.pkgName}}/{{=field.type.type}}'] = {{=getWrapperNameByType(field.type)}}; + {{?}} + {{?}} +{{~}} + +// Define the wrapper class. +class {{=objectWrapper}} { + constructor(other) { + this._rawRos = undefined; + if (other === undefined) { + this._proxyObj = {}; + } else if (other instanceof {{=objectWrapper}}) { + this._proxyObj = other._proxyObj; + } else { + this._proxyObj = other; + } + } + + static _createRosMessage() { + return typesupport.createRosMessage(); + } + + static _toJsObject(buffer, offset = 0) { + return typesupport.toJsObject(buffer, offset, typesupportDeps); + } + + static _toRosMessage(obj) { + const rosMessage = {{=objectWrapper}}._createRosMessage(); + {{=objectWrapper}}._writeRosMessage(obj, rosMessage, 0); + return rosMessage; + } + + static _writeRosMessage(obj, buffer, offset) { + typesupport.writeRosMessage(obj, buffer, offset, typesupportDeps); + } + + toRawROS() { + this.freeze(); + return this._rawRos; + } + + freeze(own = false, checkConsistency = false) { + if (Object.getOwnPropertyNames(this._proxyObj).length === 0) { + this._rawRos = {{=objectWrapper}}._createRosMessage(); + } + this._rawRos = {{=objectWrapper}}._toRosMessage(this._proxyObj); + } + + serialize() { + return this.toRawROS(); + } + + deserialize(rawRos) { + this._proxyObj = {{=objectWrapper}}._toJsObject(rawRos); + } + + toPlainObject(enableTypedArray) { + return this._proxyObj; + } + + static freeStruct(refObject) { + // managed by v8 gc + } + + static destoryRawROS(msg) { + // managed by v8 gc + } + + static type() { + return {pkgName: '{{=it.messageInfo.pkgName}}', subFolder: '{{=it.messageInfo.subFolder}}', interfaceName: '{{=it.messageInfo.interfaceName}}'}; + } + + static isPrimitive() { + return {{=isPrimitivePackage(it.spec.baseType)}}; + } + + static get isROSArray() { + return false; + } + + get refObject() { + return this._rawRos; + } + + {{~ it.spec.fields :field}} + get {{=field.name}}() { + return this._proxyObj['{{=field.name}}']; + } + + set {{=field.name}}(value) { + this._proxyObj['{{=field.name}}'] = value; + } + {{~}} + + copy(other) { + this._proxyObj = other._proxyObj; + } + + static get classType() { + return {{=objectWrapper}}; + } + + static get ROSMessageDef() { + return {{=compactMsgDefJSON}}; + } + + hasMember(name) { + let memberNames = {{=extractMemberNames(it.spec.fields)}}; + return memberNames.indexOf(name) !== -1; + } +} + +module.exports = {{=objectWrapper}}; + +/* + * The following is the original spec object coming from parser: +{{=it.json}} +*/ From 8fb92f64b7ec5a812e5e6752b52edbc48026f172 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 11 Dec 2020 14:26:20 +0800 Subject: [PATCH 29/64] pass single process test --- rosidl_gen/idl_generator.js | 35 ++++++++++++++++--------- rosidl_gen/templates/cppDefinitions.dot | 4 +-- src/type_conversion.hpp | 21 ++++++++++----- test/test-single-process.js | 2 +- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 07388da1..2f351910 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -201,6 +201,15 @@ function pascalToSnakeCase(s) { } function getRosHeaderField(messageInfo) { + if (isServiceMessage(messageInfo)) { + const interfaceName = messageInfo.interfaceName.slice( + 0, + messageInfo.interfaceName.lastIndexOf('_') + ); + return `${messageInfo.pkgName}/${messageInfo.subFolder}/${pascalToSnakeCase( + interfaceName + )}.h`; + } return `${messageInfo.pkgName}/${messageInfo.subFolder}/${pascalToSnakeCase( messageInfo.interfaceName )}.h`; @@ -326,18 +335,19 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { return getStructType(messageInfo); }; - const messages = []; + const messages = await Promise.all( + pkgInfo.messages.map(async (messageInfo) => ({ + info: messageInfo, + spec: await rosIdlDb.getMessageSpec(messageInfo), + structType: getStructType(messageInfo), + })) + ); - // this is slower but doing it sequentially maintains ordering - for (let messageInfo of pkgInfo.messages) { - if (!isServiceMessage(messageInfo)) { - messages.push({ - info: messageInfo, - spec: await rosIdlDb.getMessageSpec(messageInfo), - structType: getStructType(messageInfo), - }); - } - } + const includeHeadersSet = new Set(); + messages.forEach(({ info }) => { + includeHeadersSet.add(getRosHeaderField(info)); + }); + const includeHeaders = Array.from(includeHeadersSet.values()); const dependentPackages = await rosIdlDb.getDependentPackages(pkgName); @@ -346,10 +356,10 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { pkgName, pkgInfo, messages, + includeHeaders, dependentPackages, rosIdlDb, getStructType, - getRosHeaderField, getStructTypeFromRosType, getJsType, isInternalField, @@ -364,7 +374,6 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { dependentPackages, rosIdlDb, getStructType, - getRosHeaderField, getStructTypeFromRosType, getJsType, isInternalField, diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 35986864..75276574 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -6,8 +6,8 @@ #include "definitions.hpp" #include "../../type_conversion.hpp" -{{~ it.messages : message}} -#include <{{=it.getRosHeaderField(message.info)}}> +{{~ it.includeHeaders : header}} +#include <{{=header}}> {{~}} namespace rclnodejs { diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 7798bd23..537fae9e 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -95,14 +95,13 @@ inline uint16_t ToNativeChecked(v8::Local val) { template <> inline int64_t ToNativeChecked(v8::Local val) { - return val->ToBigInt(Nan::GetCurrentContext()).ToLocalChecked()->Int64Value(); + return val->IntegerValue(Nan::GetCurrentContext()).ToChecked(); } template <> inline uint64_t ToNativeChecked(v8::Local val) { - return val->ToBigInt(Nan::GetCurrentContext()) - .ToLocalChecked() - ->Uint64Value(); + return static_cast( + val->IntegerValue(Nan::GetCurrentContext()).ToChecked()); } template <> @@ -383,13 +382,21 @@ inline v8::Local ToJsChecked(T val) { template <> inline v8::Local ToJsChecked(int64_t val) { - return v8::BigInt::New(Nan::GetCurrentContext()->GetIsolate(), val); + // max/min safe integer + if (val > 9007199254740991 || val < -9007199254740991) { + return v8::BigInt::New(Nan::GetCurrentContext()->GetIsolate(), val); + } + return Nan::New(val); } template <> inline v8::Local ToJsChecked(uint64_t val) { - return v8::BigInt::NewFromUnsigned(Nan::GetCurrentContext()->GetIsolate(), - val); + // max/min safe integer + if (val > 9007199254740991) { + return v8::BigInt::NewFromUnsigned(Nan::GetCurrentContext()->GetIsolate(), + val); + } + return Nan::New(val); } // can't specialize const ref, probably need to use SFINAE diff --git a/test/test-single-process.js b/test/test-single-process.js index 75b871f9..6ee22d8b 100644 --- a/test/test-single-process.js +++ b/test/test-single-process.js @@ -51,7 +51,7 @@ describe('Test rclnodejs nodes in a single process', function () { 'single_ps_channel1' ); var timer = publisherNode.createTimer(100, () => { - publisher.publish(msg); + publisher.publish({ data: msg }); }); rclnodejs.spin(subscriptionNode); rclnodejs.spin(publisherNode); From f403c789b849532890f9a1369974cf49fc1d0f50 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 11 Dec 2020 14:54:41 +0800 Subject: [PATCH 30/64] support default messages --- rosidl_gen/templates/cppDefinitions.dot | 25 +++++++-- src/type_conversion.hpp | 4 +- test/test-default-messages.js | 74 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 test/test-default-messages.js diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 75276574..28da4655 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -41,12 +41,23 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{? !it.isInternalField(field)}} { auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + {{? field.default_value !== null}} + if (js_value->IsUndefined()) { + // default value initialized when message is created. + return; + } + {{?}} {{ const jsType = it.getJsType(field.type); }} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); + try { + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); + } catch (const TypeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } {{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -61,7 +72,15 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{??}} {{? field.type.isFixedSizeArray}} {{? field.type.isPrimitiveType}} - WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); + try { + WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); + } catch (const TypeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } catch (const OutOfRangeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } {{??}} // TODO: handle non-primitive arrays types auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -75,8 +94,6 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { } {{?}} {{~}} - - info.GetReturnValue().Set(Nan::Undefined()); } NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 537fae9e..3a691ef3 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -31,7 +31,7 @@ class TypeError : public std::exception { const char* what() const noexcept override { return _what.c_str(); } - std::string what_detailed(const std::string& field_name) { + std::string what_detailed(const std::string& field_name) const { return "expected \"" + field_name + "\" to be " + _expected_types; } @@ -48,7 +48,7 @@ class OutOfRangeError : public std::exception { const char* what() const noexcept override { return _what.c_str(); } - std::string what_detailed(const std::string& field_name) { + std::string what_detailed(const std::string& field_name) const { return "expected \"" + field_name + "\" to have length " + std::to_string(_len); } diff --git a/test/test-default-messages.js b/test/test-default-messages.js new file mode 100644 index 00000000..2ed9069f --- /dev/null +++ b/test/test-default-messages.js @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; + +const assert = require('assert'); +const rclnodejs = require('../index.js'); + +describe('rclnodejs message communication', function () { + this.timeout(60 * 1000); + + before(function () { + return rclnodejs.init(); + }); + + after(function () { + rclnodejs.shutdown(); + }); + + it('should publish messages with unfilled defaults', function (done) { + const publisherNode = rclnodejs.createNode('defaults_message_publisher'); + const subscriptionNode = rclnodejs.createNode( + 'defaults_message_subscriber' + ); + + const subscription = subscriptionNode.createSubscription( + 'test_msgs/msg/Defaults', + 'defaults_message_channel1', + (msg) => { + timer.cancel(); + assert.strictEqual(msg.bool_value, true); + assert.strictEqual(msg.byte_value, 50); + assert.strictEqual(msg.char_value, 100); + assert.strictEqual(msg.float32_value, 1.125); + assert.strictEqual(msg.float64_value, 1.125); + assert.strictEqual(msg.int8_value, -50); + assert.strictEqual(msg.uint8_value, 200); + assert.strictEqual(msg.int16_value, -1000); + assert.strictEqual(msg.uint16_value, 2000); + assert.strictEqual(msg.int32_value, -30000); + assert.strictEqual(msg.uint32_value, 60000); + assert.strictEqual(msg.int64_value, -40000000); + assert.strictEqual(msg.uint64_value, 50000000); + publisherNode.destroy(); + subscriptionNode.destroy(); + done(); + } + ); + + var publisher = publisherNode.createPublisher( + 'test_msgs/msg/Defaults', + 'defaults_message_channel1' + ); + var timer = publisherNode.createTimer(100, () => { + publisher.publish({}); + }); + rclnodejs.spin(subscriptionNode); + rclnodejs.spin(publisherNode); + }); +}); From 1606197daf63d229e8965060f8cdcca1c467a4da Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 11 Dec 2020 16:17:19 +0800 Subject: [PATCH 31/64] passes fixed array tests --- rosidl_gen/templates/cppDefinitions.dot | 52 ++++++--- rosidl_gen/templates/messageRosidl.dot | 1 + src/type_conversion.hpp | 101 ++++++++++-------- test/test-default-messages.js | 4 +- test/test-fixed-array.js | 134 ------------------------ test/test-fixed-arrays.js | 100 ++++++++++++++++++ 6 files changed, 198 insertions(+), 194 deletions(-) delete mode 100644 test/test-fixed-array.js create mode 100644 test/test-fixed-arrays.js diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 28da4655..f0532842 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -84,8 +84,15 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{??}} // TODO: handle non-primitive arrays types auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_func); + try { + WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_msg); + } catch (const TypeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } catch (const OutOfRangeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } {{?}} {{??}} // TODO: handle sequences @@ -102,30 +109,41 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); auto typesupport = Nan::To(info[2]).ToLocalChecked(); - auto jsObj = Nan::New(); + auto js_obj = Nan::New(); {{~ message.spec.fields : field}} -{{? !it.isInternalField(field)}} -{{? !field.type.isArray}} -{{? field.type.isPrimitiveType}} - Nan::Set(jsObj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); -{{??}} + {{? !it.isInternalField(field)}} + {{? !field.type.isArray}} + {{? field.type.isPrimitiveType}} + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); + {{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("toJsObject").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_toJsObject").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); v8::Local argv[] = { info[0], Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) }; - auto {{=field.name}}_jsObj = Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); - Nan::Set(jsObj, Nan::New("{{=field.name}}").ToLocalChecked(), {{=field.name}}_jsObj); + auto {{=field.name}}_js_obj = Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), {{=field.name}}_js_obj); } -{{?}} -{{??}} - // TODO: handle array -{{?}} -{{?}} + {{?}} + {{??}} + {{? field.type.isFixedSizeArray}} + {{? field.type.isPrimitiveType}} + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}})); + {{??}} + { + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsObjectArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}}, info[0], offset, typesupport_msg)); + } + {{?}} + {{??}} + // TODO: handle sequences + {{?}} + {{?}} + {{?}} {{~}} - info.GetReturnValue().Set(jsObj); + info.GetReturnValue().Set(js_obj); } {{~}} diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index c1243f03..55f89139 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -267,6 +267,7 @@ class {{=objectWrapper}} { freeze(own = false, checkConsistency = false) { if (Object.getOwnPropertyNames(this._proxyObj).length === 0) { this._rawRos = {{=objectWrapper}}._createRosMessage(); + return; } this._rawRos = {{=objectWrapper}}._toRosMessage(this._proxyObj); } diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 3a691ef3..e6add421 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -252,7 +252,19 @@ inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, } template -inline void WriteNativeArray(v8::Local val, T* arr, size_t len); +inline void WriteNativeArray(v8::Local val, T* arr, size_t len) { + if (!val->IsArray()) { + throw TypeError({"array"}); + } + auto array = val.As(); + if (array->Length() < len) { + throw OutOfRangeError(len); + } + for (size_t i = 0; i < len; ++i) { + auto item = Nan::Get(array, i).ToLocalChecked(); + arr[i] = ToNativeChecked(std::move(item)); + } +} template <> inline void WriteNativeArray(v8::Local val, int8_t* arr, @@ -318,43 +330,11 @@ inline void WriteNativeArray(v8::Local val, bool* arr, } } -template <> -inline void WriteNativeArray(v8::Local val, float* arr, - size_t len) { - if (!val->IsArray()) { - throw TypeError({"array"}); - } - auto array = val.As(); - if (array->Length() < len) { - throw OutOfRangeError(len); - } - for (size_t i = 0; i < len; ++i) { - auto item = Nan::Get(array, i).ToLocalChecked(); - arr[i] = static_cast(Nan::To(std::move(item)).ToChecked()); - } -} - -template <> -inline void WriteNativeArray(v8::Local val, double* arr, - size_t len) { - if (!val->IsArray()) { - throw TypeError({"array"}); - } - auto array = val.As(); - if (array->Length() < len) { - throw OutOfRangeError(len); - } - for (size_t i = 0; i < len; ++i) { - auto item = Nan::Get(array, i).ToLocalChecked(); - arr[i] = Nan::To(std::move(item)).ToChecked(); - } -} - template -inline void WriteNativeObjectArray(v8::Local val, T* arr, size_t len, - v8::Local node_buffer, - size_t offset, - v8::Local typesupport_func) { +inline void WriteNativeObjectArray( + const v8::Local& val, T* arr, size_t len, + const v8::Local& node_buffer, size_t offset, + const v8::Local& typesupport_msg) { if (!val->IsArray()) { throw TypeError({"array"}); } @@ -365,6 +345,12 @@ inline void WriteNativeObjectArray(v8::Local val, T* arr, size_t len, auto msg_base = node::Buffer::Data(node_buffer) + offset; v8::Local argv[] = {Nan::Undefined(), node_buffer, Nan::Undefined()}; + auto typesupport_func = + Nan::To( + Nan::Get(typesupport_msg, + Nan::New("_writeRosMessage").ToLocalChecked()) + .ToLocalChecked()) + .ToLocalChecked(); for (size_t i = 0; i < len; ++i) { auto item = Nan::Get(array, i).ToLocalChecked(); argv[0] = item; @@ -399,19 +385,52 @@ inline v8::Local ToJsChecked(uint64_t val) { return Nan::New(val); } -// can't specialize const ref, probably need to use SFINAE template <> inline v8::Local ToJsChecked( rosidl_runtime_c__String val) { return Nan::New(val.data).ToLocalChecked(); } -// can't specialize const ref, probably need to use SFINAE template <> inline v8::Local ToJsChecked( rosidl_runtime_c__U16String val) { - // TODO: - throw new std::runtime_error("not implemented"); + return Nan::New(u16string_to_string(reinterpret_cast(val.data))) + .ToLocalChecked(); +} + +template +inline v8::Local ToJsArrayChecked(T* arr, size_t len) { + auto js_array = Nan::New(); + for (size_t i = 0; i < len; i++) { + Nan::Set(js_array, i, ToJsChecked(arr[i])); + } + return js_array; +} + +template +inline v8::Local ToJsObjectArrayChecked( + T* arr, size_t len, const v8::Local& node_buffer, size_t offset, + const v8::Local& typesupport_msg) { + auto js_array = Nan::New(); + + auto msg_base = node::Buffer::Data(node_buffer) + offset; + v8::Local argv[] = {Nan::Undefined(), node_buffer, + Nan::Undefined()}; + auto typesupport_func = + Nan::To( + Nan::Get(typesupport_msg, Nan::New("_toJsObject").ToLocalChecked()) + .ToLocalChecked()) + .ToLocalChecked(); + + for (size_t i = 0; i < len; i++) { + argv[0] = node_buffer; + argv[1] = Nan::New( + static_cast(reinterpret_cast(&arr[i]) - msg_base)); + auto js_obj = Nan::Call(typesupport_func, Nan::New(), 2, argv) + .ToLocalChecked(); + Nan::Set(js_array, i, js_obj); + } + return js_array; } } // namespace rclnodejs diff --git a/test/test-default-messages.js b/test/test-default-messages.js index 2ed9069f..52c19307 100644 --- a/test/test-default-messages.js +++ b/test/test-default-messages.js @@ -61,11 +61,11 @@ describe('rclnodejs message communication', function () { } ); - var publisher = publisherNode.createPublisher( + const publisher = publisherNode.createPublisher( 'test_msgs/msg/Defaults', 'defaults_message_channel1' ); - var timer = publisherNode.createTimer(100, () => { + const timer = publisherNode.createTimer(100, () => { publisher.publish({}); }); rclnodejs.spin(subscriptionNode); diff --git a/test/test-fixed-array.js b/test/test-fixed-array.js deleted file mode 100644 index 234f4bfc..00000000 --- a/test/test-fixed-array.js +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -const assert = require('assert'); -const rclnodejs = require('../index.js'); - -/* eslint-disable camelcase */ -/* eslint-disable key-spacing */ -/* eslint-disable comma-spacing */ - -describe('Test message which has a fixed array of 36', function () { - this.timeout(60 * 1000); - - const mapData = { - map: { - header: { - stamp: { - sec: 123456, - nanosec: 789, - }, - frame_id: 'main_frame', - }, - info: { - map_load_time: { - sec: 123456, - nanosec: 789, - }, - resolution: 1.0, - width: 1024, - height: 768, - origin: { - position: { - x: 0.0, - y: 0.0, - z: 0.0, - }, - orientation: { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, - }, - }, - }, - data: Int8Array.from([1, 2, 3]), - }, - initial_pose: { - header: { - stamp: { - sec: 123456, - nanosec: 789, - }, - frame_id: 'main frame', - }, - pose: { - pose: { - position: { x: 11.5, y: 112.75, z: 9.0 }, - orientation: { x: 31.5, y: 21.5, z: 7.5, w: 1.5 }, - }, - covariance: Float64Array.from({ length: 36 }, (v, k) => k), - }, - }, - }; - - before(function () { - return rclnodejs.init(); - }); - - after(function () { - rclnodejs.shutdown(); - }); - - it('Assigned with an array of 36', function (done) { - const node = rclnodejs.createNode('set_map_client'); - node.createService( - 'nav_msgs/srv/SetMap', - 'set_map', - (request, response) => { - assert.deepStrictEqual(request, mapData); - response.success = true; - return response; - } - ); - - rclnodejs.spin(node); - const client = node.createClient('nav_msgs/srv/SetMap', 'set_map'); - client.sendRequest(mapData, (response) => { - assert.deepStrictEqual(response.success, true); - node.destroy(); - done(); - }); - }); - - it('Assigned with a longer array', function (done) { - mapData.initial_pose.pose.covariance = Float64Array.from( - { length: 37 }, - (v, k) => k - ); - const node = rclnodejs.createNode('set_map_client'); - const client = node.createClient('nav_msgs/srv/SetMap', 'set_map'); - assert.throws(() => { - client.sendRequest(mapData, (response) => {}); - }, RangeError); - node.destroy(); - done(); - }); - - it('Assigned with a shorter array', function (done) { - mapData.initial_pose.pose.covariance = Float64Array.from( - { length: 35 }, - (v, k) => k - ); - const node = rclnodejs.createNode('set_map_client'); - const client = node.createClient('nav_msgs/srv/SetMap', 'set_map'); - assert.throws(() => { - client.sendRequest(mapData, (response) => {}); - }, RangeError); - node.destroy(); - done(); - }); -}); diff --git a/test/test-fixed-arrays.js b/test/test-fixed-arrays.js new file mode 100644 index 00000000..f8cd1dc1 --- /dev/null +++ b/test/test-fixed-arrays.js @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; + +const assert = require('assert'); +const rclnodejs = require('../index.js'); + +describe('rclnodejs message communication', function () { + this.timeout(60 * 1000); + + before(function () { + return rclnodejs.init(); + }); + + after(function () { + rclnodejs.shutdown(); + }); + + it('should publish messages with fixed arrays', function (done) { + const publisherNode = rclnodejs.createNode('fixed_arrays_publisher'); + const subscriptionNode = rclnodejs.createNode('fixed_arrays_subscriber'); + const originalMsg = { + bool_values: [true, true, false], + byte_values: [0, 1, 2], + char_values: [0, 1, 2], + float32_values: [0, 1, 2], + float64_values: [0, 1, 2], + int8_values: [0, 1, 2], + uint8_values: [0, 1, 2], + int16_values: [0, 1, 2], + uint16_values: [0, 1, 2], + int32_values: [0, 1, 2], + uint32_values: [0, 1, 2], + int64_values: [0, 1, 2], + uint64_values: [0, 1, 2], + string_values: ['a', 'b', 'c'], + basic_types_values: [{}, {}, {}], + constants_values: [{}, {}, {}], + defaults_values: [{}, {}, {}], + alignment_check: 0, + }; + + const subscription = subscriptionNode.createSubscription( + 'test_msgs/msg/Arrays', + 'fixed_arrays_channel1', + (msg) => { + timer.cancel(); + assert.deepStrictEqual(msg.bool_values, originalMsg.bool_values); + assert.deepStrictEqual(msg.byte_values, originalMsg.byte_values); + assert.deepStrictEqual(msg.char_values, originalMsg.char_values); + assert.deepStrictEqual(msg.float32_values, originalMsg.float32_values); + assert.deepStrictEqual(msg.float64_values, originalMsg.float64_values); + assert.deepStrictEqual(msg.int8_values, originalMsg.int8_values); + assert.deepStrictEqual(msg.uint8_values, originalMsg.uint8_values); + assert.deepStrictEqual(msg.int16_values, originalMsg.int16_values); + assert.deepStrictEqual(msg.uint16_values, originalMsg.uint16_values); + assert.deepStrictEqual(msg.int32_values, originalMsg.int32_values); + assert.deepStrictEqual(msg.uint32_values, originalMsg.uint32_values); + assert.deepStrictEqual(msg.int64_values, originalMsg.int64_values); + assert.deepStrictEqual(msg.uint64_values, originalMsg.uint64_values); + assert.deepStrictEqual(msg.string_values, originalMsg.string_values); + assert.strictEqual(msg.alignment_check, 0); + assert.strictEqual(msg.defaults_values[0].bool_value, true); + assert.strictEqual(msg.defaults_values[1].bool_value, true); + assert.strictEqual(msg.defaults_values[2].bool_value, true); + assert.strictEqual(msg.defaults_values[0].int8_value, -50); + assert.strictEqual(msg.defaults_values[1].int8_value, -50); + assert.strictEqual(msg.defaults_values[2].int8_value, -50); + publisherNode.destroy(); + subscriptionNode.destroy(); + done(); + } + ); + + const publisher = publisherNode.createPublisher( + 'test_msgs/msg/Arrays', + 'fixed_arrays_channel1' + ); + const timer = publisherNode.createTimer(100, () => { + publisher.publish(originalMsg); + }); + rclnodejs.spin(subscriptionNode); + rclnodejs.spin(publisherNode); + }); +}); From a247084fd8fe80040e1a231d161976dc35644c64 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 11 Dec 2020 16:42:37 +0800 Subject: [PATCH 32/64] additional tests for default values --- rosidl_gen/templates/cppDefinitions.dot | 68 ++++++++++--------------- test/test-default-messages.js | 41 +++++++++++++++ 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index f0532842..859ea826 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -37,70 +37,56 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); auto typesupport = Nan::To(info[3]).ToLocalChecked(); + try { {{~ message.spec.fields : field}} {{? !it.isInternalField(field)}} - { - auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + [&](){ + auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); {{? field.default_value !== null}} - if (js_value->IsUndefined()) { - // default value initialized when message is created. - return; - } + if (js_value->IsUndefined()) { + // default value is initialized when message is created. + return; + } {{?}} {{ const jsType = it.getJsType(field.type); }} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - try { msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); - } catch (const TypeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } {{??}} - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto {{=field.name}}_js_obj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); - v8::Local argv[] = { - {{=field.name}}_js_obj, - info[1], - Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - reinterpret_cast(msg))) - }; - Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto {{=field.name}}_js_obj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + {{=field.name}}_js_obj, + info[1], + Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - reinterpret_cast(msg))) + }; + Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); {{?}} {{??}} {{? field.type.isFixedSizeArray}} {{? field.type.isPrimitiveType}} - try { WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); - } catch (const TypeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } catch (const OutOfRangeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } {{??}} - // TODO: handle non-primitive arrays types - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - try { + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_msg); - } catch (const TypeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } catch (const OutOfRangeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } {{?}} {{??}} - // TODO: handle sequences + // TODO: handle sequences {{?}} {{?}} - } + }(); {{?}} {{~}} + } catch (const TypeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } catch (const OutOfRangeError& e) { + Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + return; + } } NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { @@ -138,7 +124,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { } {{?}} {{??}} - // TODO: handle sequences + // TODO: handle sequences {{?}} {{?}} {{?}} diff --git a/test/test-default-messages.js b/test/test-default-messages.js index 52c19307..b7bf9430 100644 --- a/test/test-default-messages.js +++ b/test/test-default-messages.js @@ -71,4 +71,45 @@ describe('rclnodejs message communication', function () { rclnodejs.spin(subscriptionNode); rclnodejs.spin(publisherNode); }); + + it.only('overwrites the default values when it is provided', function (done) { + const publisherNode = rclnodejs.createNode('defaults_message_publisher'); + const subscriptionNode = rclnodejs.createNode( + 'defaults_message_subscriber' + ); + + const subscription = subscriptionNode.createSubscription( + 'test_msgs/msg/Defaults', + 'defaults_message_channel2', + (msg) => { + timer.cancel(); + assert.strictEqual(msg.bool_value, true); + assert.strictEqual(msg.byte_value, 50); + assert.strictEqual(msg.char_value, 100); + assert.strictEqual(msg.float32_value, 1.125); + assert.strictEqual(msg.float64_value, 1.125); + assert.strictEqual(msg.int8_value, -51); + assert.strictEqual(msg.uint8_value, 200); + assert.strictEqual(msg.int16_value, -1000); + assert.strictEqual(msg.uint16_value, 2000); + assert.strictEqual(msg.int32_value, -30000); + assert.strictEqual(msg.uint32_value, 60000); + assert.strictEqual(msg.int64_value, -40000000); + assert.strictEqual(msg.uint64_value, 50000000); + publisherNode.destroy(); + subscriptionNode.destroy(); + done(); + } + ); + + const publisher = publisherNode.createPublisher( + 'test_msgs/msg/Defaults', + 'defaults_message_channel2' + ); + const timer = publisherNode.createTimer(100, () => { + publisher.publish({ int8_value: -51 }); + }); + rclnodejs.spin(subscriptionNode); + rclnodejs.spin(publisherNode); + }); }); From bd6688d12943d0c17b05b3faa0e5058dc7e18885 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 14 Dec 2020 14:45:23 +0800 Subject: [PATCH 33/64] publishing sequences --- rosidl_gen/templates/cppDefinitions.dot | 120 +++++++----- rosidl_gen/templates/cppDefinitionsHeader.dot | 2 + rosidl_gen/templates/messageRosidl.dot | 8 +- src/type_conversion.hpp | 180 ++++++++++++++++-- test/test-default-messages.js | 2 +- 5 files changed, 241 insertions(+), 71 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 859ea826..e35d4e29 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -3,6 +3,10 @@ // *** DO NOT EDIT directly // +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + #include "definitions.hpp" #include "../../type_conversion.hpp" @@ -19,6 +23,7 @@ NAN_MODULE_INIT(rclnodejs__{{=message.structType}}::Init) { clazz->Set(Nan::New("createRosMessage").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::CreateRosMessage)); clazz->Set(Nan::New("writeRosMessage").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::WriteRosMessage)); clazz->Set(Nan::New("toJsObject").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::ToJsObject)); + clazz->Set(Nan::New("initSequence").ToLocalChecked(), Nan::New(rclnodejs__{{=message.structType}}::InitSequence)); Nan::Set(target, Nan::New("{{=message.info.interfaceName}}").ToLocalChecked(), Nan::GetFunction(clazz).ToLocalChecked()); } @@ -31,62 +36,75 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::CreateRosMessage) { } NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { - auto jsObj = Nan::To(info[0]).ToLocalChecked(); - auto* buffer = node::Buffer::Data(info[1]); - auto offset = Nan::To(info[2]).ToChecked(); - auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); - auto typesupport = Nan::To(info[3]).ToLocalChecked(); + auto typesupport = Nan::To(info[0]).ToLocalChecked(); + auto js_obj = Nan::To(info[1]).ToLocalChecked(); + {{=message.structType}}* msg; + if (info[2]->IsExternal()) { + msg = reinterpret_cast<{{=message.structType}}*>(info[2].As()->Value()); + } else { + auto* buffer = node::Buffer::Data(info[2]); + auto offset = Nan::To(info[3]).ToChecked(); + msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); + } +{{~ message.spec.fields : field}} +{{? !it.isInternalField(field)}} try { - {{~ message.spec.fields : field}} - {{? !it.isInternalField(field)}} [&](){ - auto js_value = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); - {{? field.default_value !== null}} + auto js_value = Nan::Get(js_obj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); +{{? field.default_value !== null}} if (js_value->IsUndefined()) { // default value is initialized when message is created. return; } - {{?}} +{{?}} {{ const jsType = it.getJsType(field.type); }} - {{? !field.type.isArray}} - {{? field.type.isPrimitiveType}} +{{? !field.type.isArray}} +{{? field.type.isPrimitiveType}} msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); - {{??}} +{{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto {{=field.name}}_js_obj = Nan::Get(jsObj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); v8::Local argv[] = { - {{=field.name}}_js_obj, - info[1], - Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - reinterpret_cast(msg))) + js_value, + Nan::New(&msg->{{=field.name}}) }; - Nan::Call(typesupport_func, Nan::New(), 3, argv).ToLocalChecked(); - {{?}} - {{??}} - {{? field.type.isFixedSizeArray}} - {{? field.type.isPrimitiveType}} + Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); +{{?}} +{{??}} +{{? field.type.isFixedSizeArray}} +{{? field.type.isPrimitiveType}} WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); - {{??}} +{{??}} + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, typesupport_msg); +{{?}} +{{??}} +{{? field.type.arraySize === null}} + size_t capacity = 0xffffffffffffffff; +{{??}} + size_t capacity = {{=field.type.arraySize}}; +{{?}} +{{? field.type.isPrimitiveType}} + WriteNativeSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity); +{{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, info[1], offset, typesupport_msg); - {{?}} - {{??}} - // TODO: handle sequences - {{?}} - {{?}} + WriteNativeObjectSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); +{{?}} +{{?}} +{{?}} }(); - {{?}} -{{~}} } catch (const TypeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + Nan::ThrowTypeError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); return; } catch (const OutOfRangeError& e) { - Nan::ThrowError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); + Nan::ThrowRangeError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); return; } +{{?}} +{{~}} } NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { @@ -97,11 +115,11 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { auto js_obj = Nan::New(); {{~ message.spec.fields : field}} - {{? !it.isInternalField(field)}} - {{? !field.type.isArray}} - {{? field.type.isPrimitiveType}} +{{? !it.isInternalField(field)}} +{{? !field.type.isArray}} +{{? field.type.isPrimitiveType}} Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); - {{??}} +{{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_toJsObject").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); @@ -112,26 +130,32 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { auto {{=field.name}}_js_obj = Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), {{=field.name}}_js_obj); } - {{?}} - {{??}} - {{? field.type.isFixedSizeArray}} - {{? field.type.isPrimitiveType}} +{{?}} +{{??}} +{{? field.type.isFixedSizeArray}} +{{? field.type.isPrimitiveType}} Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}})); - {{??}} +{{??}} { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsObjectArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}}, info[0], offset, typesupport_msg)); } - {{?}} - {{??}} +{{?}} +{{??}} // TODO: handle sequences - {{?}} - {{?}} - {{?}} +{{?}} +{{?}} +{{?}} {{~}} info.GetReturnValue().Set(js_obj); } +NAN_METHOD(rclnodejs__{{=message.structType}}::InitSequence) { + auto size = Nan::To(info[0]).ToChecked(); + auto* msg = reinterpret_cast<{{=message.structType}}__Sequence*>(info[1].As()->Value()); + {{=message.structType}}__Sequence__init(msg, size); +} + {{~}} NAN_MODULE_WORKER_ENABLED({{=it.pkgName}}, [](auto target) { @@ -141,3 +165,5 @@ NAN_MODULE_WORKER_ENABLED({{=it.pkgName}}, [](auto target) { }); } // namespace rclnodejs + +#pragma GCC diagnostic pop diff --git a/rosidl_gen/templates/cppDefinitionsHeader.dot b/rosidl_gen/templates/cppDefinitionsHeader.dot index aa500a3e..5ce06a65 100644 --- a/rosidl_gen/templates/cppDefinitionsHeader.dot +++ b/rosidl_gen/templates/cppDefinitionsHeader.dot @@ -21,6 +21,8 @@ class rclnodejs__{{=message.structType}} { static NAN_METHOD(WriteRosMessage); static NAN_METHOD(ToJsObject); + + static NAN_METHOD(InitSequence); }; {{~}} diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 55f89139..08c0f638 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -164,7 +164,7 @@ const currentTypedArrayElementType = getTypedArrayElementName(it.spec.baseType); function shouldRequire(baseType, fieldType) { let requiredModule = '{{=getPackageNameByType(fieldType)}}/{{=getModulePathByType(fieldType)}}'; - let shouldRequire = !isPrimitivePackage(baseType) && (fieldType.isArray || !fieldType.isPrimitiveType || fieldType.type === 'string'); + let shouldRequire = !isPrimitivePackage(baseType) && !fieldType.isPrimitiveType; if (shouldRequire && !isExisted(requiredModule)) { existedModules.push(requiredModule); @@ -256,7 +256,11 @@ class {{=objectWrapper}} { } static _writeRosMessage(obj, buffer, offset) { - typesupport.writeRosMessage(obj, buffer, offset, typesupportDeps); + typesupport.writeRosMessage(typesupportDeps, obj, buffer, offset); + } + + static _initSequence(size, msg) { + typesupport.initSequence(size, msg); } toRawROS() { diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index e6add421..2ae20620 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -2,6 +2,8 @@ #define RCLNODEJS_TYPE_CONVERSION_HPP_ #include +#include +#include #include #include #include @@ -112,12 +114,15 @@ inline float ToNativeChecked(v8::Local val) { template <> inline rosidl_runtime_c__String ToNativeChecked( v8::Local val) { + rosidl_runtime_c__String ros_string; + rosidl_runtime_c__String__init(&ros_string); + if (!val->IsString()) { + return ros_string; + }; Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); } - rosidl_runtime_c__String ros_string; - rosidl_runtime_c__String__init(&ros_string); rosidl_runtime_c__String__assign(&ros_string, *utf8); return ros_string; } @@ -125,16 +130,16 @@ inline rosidl_runtime_c__String ToNativeChecked( template <> inline rosidl_runtime_c__U16String ToNativeChecked( v8::Local val) { + rosidl_runtime_c__U16String ros_string; + rosidl_runtime_c__U16String__init(&ros_string); if (!val->IsString()) { - throw TypeError({"string"}); + return ros_string; }; Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); } auto u16s = string_to_u16string(*utf8); - rosidl_runtime_c__U16String ros_string; - rosidl_runtime_c__U16String__init(&ros_string); rosidl_runtime_c__U16String__assign( &ros_string, reinterpret_cast(u16s.c_str())); return ros_string; @@ -231,11 +236,11 @@ inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, size_t len) { if (!IsTypedArray(val)) { if (!val->IsArray()) { - throw TypeError({"array", TypedArrayName::Name}); + return; } auto array = val.As(); if (array->Length() < len) { - throw OutOfRangeError(len); + len = array->Length(); } for (uint32_t i = 0; i < len; ++i) { auto native = @@ -245,7 +250,7 @@ inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, } else { auto typed_array = val.As(); if (typed_array->Length() < len) { - throw OutOfRangeError(len); + len = typed_array->Length(); } typed_array->CopyContents(arr, len * sizeof(NativeT)); } @@ -254,11 +259,11 @@ inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, template inline void WriteNativeArray(v8::Local val, T* arr, size_t len) { if (!val->IsArray()) { - throw TypeError({"array"}); + return; } auto array = val.As(); if (array->Length() < len) { - throw OutOfRangeError(len); + len = array->Length(); } for (size_t i = 0; i < len; ++i) { auto item = Nan::Get(array, i).ToLocalChecked(); @@ -318,11 +323,11 @@ template <> inline void WriteNativeArray(v8::Local val, bool* arr, size_t len) { if (!val->IsArray()) { - throw TypeError({"array"}); + return; } auto array = val.As(); if (array->Length() < len) { - throw OutOfRangeError(len); + len = array->Length(); } for (size_t i = 0; i < len; ++i) { auto item = Nan::Get(array, i).ToLocalChecked(); @@ -333,18 +338,15 @@ inline void WriteNativeArray(v8::Local val, bool* arr, template inline void WriteNativeObjectArray( const v8::Local& val, T* arr, size_t len, - const v8::Local& node_buffer, size_t offset, const v8::Local& typesupport_msg) { if (!val->IsArray()) { - throw TypeError({"array"}); + return; } auto array = val.As(); if (array->Length() < len) { - throw OutOfRangeError(len); + len = array->Length(); } - auto msg_base = node::Buffer::Data(node_buffer) + offset; - v8::Local argv[] = {Nan::Undefined(), node_buffer, - Nan::Undefined()}; + v8::Local argv[2]; auto typesupport_func = Nan::To( Nan::Get(typesupport_msg, @@ -354,13 +356,149 @@ inline void WriteNativeObjectArray( for (size_t i = 0; i < len; ++i) { auto item = Nan::Get(array, i).ToLocalChecked(); argv[0] = item; - argv[2] = Nan::New( - static_cast(reinterpret_cast(&arr[i]) - msg_base)); - Nan::Call(typesupport_func, Nan::New(), 3, argv) + argv[1] = Nan::New(&arr[i]); + Nan::Call(typesupport_func, Nan::New(), 2, argv) .ToLocalChecked(); } } +template +inline void InitSequence(SequenceT* seq, size_t size); + +template <> +inline void InitSequence( + rosidl_runtime_c__bool__Sequence* seq, size_t size) { + rosidl_runtime_c__bool__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__byte__Sequence* seq, size_t size) { + rosidl_runtime_c__byte__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__char__Sequence* seq, size_t size) { + rosidl_runtime_c__char__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__float__Sequence* seq, size_t size) { + rosidl_runtime_c__float__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__double__Sequence* seq, size_t size) { + rosidl_runtime_c__double__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__int8__Sequence* seq, size_t size) { + rosidl_runtime_c__int8__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__uint8__Sequence* seq, size_t size) { + rosidl_runtime_c__uint8__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__int16__Sequence* seq, size_t size) { + rosidl_runtime_c__int16__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__uint16__Sequence* seq, size_t size) { + rosidl_runtime_c__uint16__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__int32__Sequence* seq, size_t size) { + rosidl_runtime_c__int32__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__uint32__Sequence* seq, size_t size) { + rosidl_runtime_c__uint32__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__int64__Sequence* seq, size_t size) { + rosidl_runtime_c__int64__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__uint64__Sequence* seq, size_t size) { + rosidl_runtime_c__uint64__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__String__Sequence* seq, size_t size) { + rosidl_runtime_c__String__Sequence__init(seq, size); +} + +template <> +inline void InitSequence( + rosidl_runtime_c__U16String__Sequence* seq, size_t size) { + rosidl_runtime_c__U16String__Sequence__init(seq, size); +} + +template +inline void WriteNativeSequence(v8::Local val, SequenceT* seq, + size_t capacity) { + if (!val->IsTypedArray() && !val->IsArray()) { + return; + } + uint32_t len; + if (val->IsTypedArray()) { + len = val.As()->Length(); + } else { + len = val.As()->Length(); + } + if (capacity < len) { + len = capacity; + } + InitSequence(seq, len); + WriteNativeArray(val, seq->data, len); +} + +template +inline void WriteNativeObjectSequence( + const v8::Local& val, SequenceT* seq, size_t capacity, + const v8::Local& typesupport_msg) { + if (!val->IsArray()) { + return; + } + auto array = val.As(); + + auto len = array->Length(); + if (capacity < len) { + len = capacity; + } + + auto typesupport_func = + Nan::To( + Nan::Get(typesupport_msg, Nan::New("_initSequence").ToLocalChecked()) + .ToLocalChecked()) + .ToLocalChecked(); + v8::Local argv[] = {Nan::New(len), Nan::New(seq)}; + Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); + + WriteNativeObjectArray(val, seq->data, len, typesupport_msg); +} + template inline v8::Local ToJsChecked(T val) { return Nan::New(val); diff --git a/test/test-default-messages.js b/test/test-default-messages.js index b7bf9430..ca38ba23 100644 --- a/test/test-default-messages.js +++ b/test/test-default-messages.js @@ -72,7 +72,7 @@ describe('rclnodejs message communication', function () { rclnodejs.spin(publisherNode); }); - it.only('overwrites the default values when it is provided', function (done) { + it('overwrites the default values when it is provided', function (done) { const publisherNode = rclnodejs.createNode('defaults_message_publisher'); const subscriptionNode = rclnodejs.createNode( 'defaults_message_subscriber' From cbed71858fc60b48a606d51a3885809af73bcb16 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Mon, 14 Dec 2020 14:48:15 +0800 Subject: [PATCH 34/64] remove exception, silently fill with "zero" or "default" value if incompatible type --- rosidl_gen/templates/cppDefinitions.dot | 56 +++++++---------- src/type_conversion.hpp | 84 ------------------------- 2 files changed, 24 insertions(+), 116 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index e35d4e29..5d552444 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -49,60 +49,52 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{~ message.spec.fields : field}} {{? !it.isInternalField(field)}} - try { - [&](){ - auto js_value = Nan::Get(js_obj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); + [&](){ + auto js_value = Nan::Get(js_obj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); {{? field.default_value !== null}} - if (js_value->IsUndefined()) { - // default value is initialized when message is created. - return; - } + if (js_value->IsUndefined()) { + // default value is initialized when message is created. + return; + } {{?}} {{ - const jsType = it.getJsType(field.type); +const jsType = it.getJsType(field.type); }} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); + msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); {{??}} - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - v8::Local argv[] = { - js_value, - Nan::New(&msg->{{=field.name}}) - }; - Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_writeRosMessage").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + v8::Local argv[] = { + js_value, + Nan::New(&msg->{{=field.name}}) + }; + Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); {{?}} {{??}} {{? field.type.isFixedSizeArray}} {{? field.type.isPrimitiveType}} - WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); + WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); {{??}} - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, typesupport_msg); + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, typesupport_msg); {{?}} {{??}} {{? field.type.arraySize === null}} - size_t capacity = 0xffffffffffffffff; + size_t capacity = 0xffffffffffffffff; {{??}} - size_t capacity = {{=field.type.arraySize}}; + size_t capacity = {{=field.type.arraySize}}; {{?}} {{? field.type.isPrimitiveType}} - WriteNativeSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity); + WriteNativeSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity); {{??}} - auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + WriteNativeObjectSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); {{?}} {{?}} {{?}} - }(); - } catch (const TypeError& e) { - Nan::ThrowTypeError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } catch (const OutOfRangeError& e) { - Nan::ThrowRangeError(Nan::New(e.what_detailed("{{=field.name}}")).ToLocalChecked()); - return; - } + }(); {{?}} {{~}} } diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 2ae20620..1c21e672 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -19,47 +19,6 @@ namespace rclnodejs { -class TypeError : public std::exception { - public: - explicit TypeError(const std::vector& expected_types) { - std::ostringstream oss; - for (size_t i = 0; i < expected_types.size() - 1; ++i) { - oss << expected_types[i] << " or "; - } - oss << expected_types[expected_types.size() - 1]; - _expected_types = oss.str(); - _what = "expected " + _expected_types; - } - - const char* what() const noexcept override { return _what.c_str(); } - - std::string what_detailed(const std::string& field_name) const { - return "expected \"" + field_name + "\" to be " + _expected_types; - } - - private: - std::string _expected_types; - std::string _what; -}; - -class OutOfRangeError : public std::exception { - public: - explicit OutOfRangeError(size_t len) : _len(len) { - _what = "expected array to have length " + len; - } - - const char* what() const noexcept override { return _what.c_str(); } - - std::string what_detailed(const std::string& field_name) const { - return "expected \"" + field_name + "\" to have length " + - std::to_string(_len); - } - - private: - std::string _what; - size_t _len; -}; - std::u16string string_to_u16string(const std::string& input) { std::wstring_convert, char16_t> converter; return converter.from_bytes(input); @@ -145,49 +104,6 @@ inline rosidl_runtime_c__U16String ToNativeChecked( return ros_string; } -template -struct TypedArrayName {}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Int8Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Uint8Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Int16Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Uint16Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Int32Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "Uint32Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "BigInt64Array"; -}; - -template <> -struct TypedArrayName { - static constexpr const char* Name = "BigUint64Array"; -}; - template inline bool IsTypedArray(v8::Local val); From 51e3c51946d394bca154a2714aaa63312483af34 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 15 Dec 2020 16:42:31 +0800 Subject: [PATCH 35/64] support sequences --- rosidl_gen/templates/cppDefinitions.dot | 52 ++++++++------ rosidl_gen/templates/messageRosidl.dot | 14 ++-- src/type_conversion.hpp | 95 +++++++++++++++++++++---- test/test-array.js | 1 + test/test-fixed-arrays.js | 70 ++++++++++++++---- 5 files changed, 176 insertions(+), 56 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 5d552444..69e5b446 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -42,9 +42,9 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { if (info[2]->IsExternal()) { msg = reinterpret_cast<{{=message.structType}}*>(info[2].As()->Value()); } else { - auto* buffer = node::Buffer::Data(info[2]); - auto offset = Nan::To(info[3]).ToChecked(); - msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); + auto* data = node::Buffer::Data(info[2]); + auto offset = info[2].As()->ByteOffset(); + msg = reinterpret_cast<{{=message.structType}}*>(data + offset); } {{~ message.spec.fields : field}} @@ -75,10 +75,10 @@ const jsType = it.getJsType(field.type); {{??}} {{? field.type.isFixedSizeArray}} {{? field.type.isPrimitiveType}} - WriteNativeArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); + WriteNativeArray{{=field.name}})>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}); {{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectArray{{=field.name}})>>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, typesupport_msg); + WriteNativeObjectArray{{=field.name}})>>(js_value, msg->{{=field.name}}, {{=field.type.arraySize}}, typesupport_msg); {{?}} {{??}} {{? field.type.arraySize === null}} @@ -87,10 +87,10 @@ const jsType = it.getJsType(field.type); size_t capacity = {{=field.type.arraySize}}; {{?}} {{? field.type.isPrimitiveType}} - WriteNativeSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity); + WriteNativeSequence{{=field.name}})>>(js_value, &msg->{{=field.name}}, capacity); {{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - WriteNativeObjectSequence{{=field.name}})>>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); + WriteNativeObjectSequence{{=field.name}})>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); {{?}} {{?}} {{?}} @@ -100,43 +100,51 @@ const jsType = it.getJsType(field.type); } NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { - auto* buffer = node::Buffer::Data(info[0]); - uint32_t offset = Nan::To(info[1]).ToChecked(); - auto* msg = reinterpret_cast<{{=message.structType}}*>(buffer + offset); - auto typesupport = Nan::To(info[2]).ToLocalChecked(); + auto typesupport = Nan::To(info[0]).ToLocalChecked(); + auto buffer = info[1].As()->Buffer(); + auto* data = reinterpret_cast(buffer->GetContents().Data()); + auto offset = info[1].As()->ByteOffset(); + auto* msg = reinterpret_cast<{{=message.structType}}*>(data + offset); auto js_obj = Nan::New(); {{~ message.spec.fields : field}} {{? !it.isInternalField(field)}} + { {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} - Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsChecked(msg->{{=field.name}})); {{??}} - { + auto child_buffer = v8::Uint8Array::New(buffer, reinterpret_cast(&msg->{{=field.name}}) - data, sizeof(msg->{{=field.name}})); auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); auto typesupport_func = Nan::To(Nan::Get(typesupport_msg, Nan::New("_toJsObject").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); v8::Local argv[] = { - info[0], - Nan::New(static_cast(reinterpret_cast(&msg->{{=field.name}}) - buffer)) + std::move(child_buffer) }; - auto {{=field.name}}_js_obj = Nan::Call(typesupport_func, Nan::New(), 2, argv).ToLocalChecked(); + auto {{=field.name}}_js_obj = Nan::Call(typesupport_func, Nan::New(), 1, argv).ToLocalChecked(); Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), {{=field.name}}_js_obj); - } {{?}} {{??}} {{? field.type.isFixedSizeArray}} + size_t field_offset = reinterpret_cast(msg->{{=field.name}}) - data; {{? field.type.isPrimitiveType}} - Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}})); + auto js_array = ToJsArrayChecked{{=field.name}})>>(buffer, field_offset, {{=field.type.arraySize}}); + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), std::move(js_array)); {{??}} - { auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); - Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsObjectArrayChecked(msg->{{=field.name}}, {{=field.type.arraySize}}, info[0], offset, typesupport_msg)); - } + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsObjectArrayChecked{{=field.name}})>>(buffer, field_offset, {{=field.type.arraySize}}, typesupport_msg)); {{?}} {{??}} - // TODO: handle sequences + auto sequence_buffer = Nan::NewBuffer(reinterpret_cast(msg->{{=field.name}}.data), msg->{{=field.name}}.size * sizeof(decltype(*msg->{{=field.name}}.data)), [](char*, void*) {}, nullptr).ToLocalChecked().As(); + Nan::Set(sequence_buffer, Nan::New("_rclnodejs_owner").ToLocalChecked(), info[1]).ToChecked(); +{{? field.type.isPrimitiveType}} + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsArrayChecked{{=field.name}}.data)>>(sequence_buffer->Buffer(), 0, msg->{{=field.name}}.size)); +{{??}} + auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); + Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsObjectArrayChecked{{=field.name}}.data)>>(sequence_buffer->Buffer(), 0, msg->{{=field.name}}.size, typesupport_msg)); {{?}} {{?}} +{{?}} + } {{?}} {{~}} info.GetReturnValue().Set(js_obj); diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 08c0f638..9c733ea4 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -245,22 +245,22 @@ class {{=objectWrapper}} { return typesupport.createRosMessage(); } - static _toJsObject(buffer, offset = 0) { - return typesupport.toJsObject(buffer, offset, typesupportDeps); + static _toJsObject(rawRos) { + return typesupport.toJsObject(typesupportDeps, rawRos); } static _toRosMessage(obj) { const rosMessage = {{=objectWrapper}}._createRosMessage(); - {{=objectWrapper}}._writeRosMessage(obj, rosMessage, 0); + {{=objectWrapper}}._writeRosMessage(obj, rosMessage); return rosMessage; } - static _writeRosMessage(obj, buffer, offset) { - typesupport.writeRosMessage(typesupportDeps, obj, buffer, offset); + static _writeRosMessage(obj, rawRos) { + typesupport.writeRosMessage(typesupportDeps, obj, rawRos); } - static _initSequence(size, msg) { - typesupport.initSequence(size, msg); + static _initSequence(size, rawRos) { + typesupport.initSequence(size, rawRos); } toRawROS() { diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 1c21e672..2884dbbc 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -452,35 +452,104 @@ inline v8::Local ToJsChecked( .ToLocalChecked(); } +inline uint32_t JsArrayMaxLength() { + return std::numeric_limits::max(); +} + template -inline v8::Local ToJsArrayChecked(T* arr, size_t len) { +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { auto js_array = Nan::New(); - for (size_t i = 0; i < len; i++) { + auto* data = reinterpret_cast(buffer->GetContents().Data()); + auto* arr = reinterpret_cast(data + offset); + uint32_t js_len = len > JsArrayMaxLength() ? JsArrayMaxLength() : len; + for (uint32_t i = 0; i < js_len; i++) { Nan::Set(js_array, i, ToJsChecked(arr[i])); } return js_array; } +template +inline v8::Local _ToJsTypedArray( + const v8::Local& buffer, size_t offset, size_t len) { + return TypedArrayT::New(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + +template <> +inline v8::Local ToJsArrayChecked( + const v8::Local& buffer, size_t offset, size_t len) { + return _ToJsTypedArray(buffer, offset, len); +} + template inline v8::Local ToJsObjectArrayChecked( - T* arr, size_t len, const v8::Local& node_buffer, size_t offset, + const v8::Local& buffer, size_t offset, size_t len, const v8::Local& typesupport_msg) { auto js_array = Nan::New(); - - auto msg_base = node::Buffer::Data(node_buffer) + offset; - v8::Local argv[] = {Nan::Undefined(), node_buffer, - Nan::Undefined()}; + uint32_t js_len = len > JsArrayMaxLength() ? JsArrayMaxLength() : len; auto typesupport_func = Nan::To( Nan::Get(typesupport_msg, Nan::New("_toJsObject").ToLocalChecked()) .ToLocalChecked()) .ToLocalChecked(); - - for (size_t i = 0; i < len; i++) { - argv[0] = node_buffer; - argv[1] = Nan::New( - static_cast(reinterpret_cast(&arr[i]) - msg_base)); - auto js_obj = Nan::Call(typesupport_func, Nan::New(), 2, argv) + v8::Local argv[1]; + for (uint32_t i = 0; i < js_len; ++i) { + argv[0] = v8::Uint8Array::New(buffer, offset, len * sizeof(T)); + auto js_obj = Nan::Call(typesupport_func, Nan::New(), 1, argv) .ToLocalChecked(); Nan::Set(js_array, i, js_obj); } diff --git a/test/test-array.js b/test/test-array.js index 65214e56..9f80d427 100644 --- a/test/test-array.js +++ b/test/test-array.js @@ -38,6 +38,7 @@ describe('rclnodejs message communication', function () { JointState, 'JointState', (state) => { + console.log(state.position); assert.deepStrictEqual(state.header.stamp.sec, 123456); assert.deepStrictEqual(state.header.stamp.nanosec, 789); assert.deepStrictEqual(state.header.frame_id, 'main frame'); diff --git a/test/test-fixed-arrays.js b/test/test-fixed-arrays.js index f8cd1dc1..88829ca5 100644 --- a/test/test-fixed-arrays.js +++ b/test/test-fixed-arrays.js @@ -60,20 +60,62 @@ describe('rclnodejs message communication', function () { 'fixed_arrays_channel1', (msg) => { timer.cancel(); - assert.deepStrictEqual(msg.bool_values, originalMsg.bool_values); - assert.deepStrictEqual(msg.byte_values, originalMsg.byte_values); - assert.deepStrictEqual(msg.char_values, originalMsg.char_values); - assert.deepStrictEqual(msg.float32_values, originalMsg.float32_values); - assert.deepStrictEqual(msg.float64_values, originalMsg.float64_values); - assert.deepStrictEqual(msg.int8_values, originalMsg.int8_values); - assert.deepStrictEqual(msg.uint8_values, originalMsg.uint8_values); - assert.deepStrictEqual(msg.int16_values, originalMsg.int16_values); - assert.deepStrictEqual(msg.uint16_values, originalMsg.uint16_values); - assert.deepStrictEqual(msg.int32_values, originalMsg.int32_values); - assert.deepStrictEqual(msg.uint32_values, originalMsg.uint32_values); - assert.deepStrictEqual(msg.int64_values, originalMsg.int64_values); - assert.deepStrictEqual(msg.uint64_values, originalMsg.uint64_values); - assert.deepStrictEqual(msg.string_values, originalMsg.string_values); + assert.deepStrictEqual( + Array.from(msg.bool_values), + originalMsg.bool_values + ); + assert.deepStrictEqual( + Array.from(msg.byte_values), + originalMsg.byte_values + ); + assert.deepStrictEqual( + Array.from(msg.char_values), + originalMsg.char_values + ); + assert.deepStrictEqual( + Array.from(msg.float32_values), + originalMsg.float32_values + ); + assert.deepStrictEqual( + Array.from(msg.float64_values), + originalMsg.float64_values + ); + assert.deepStrictEqual( + Array.from(msg.int8_values), + originalMsg.int8_values + ); + assert.deepStrictEqual( + Array.from(msg.uint8_values), + originalMsg.uint8_values + ); + assert.deepStrictEqual( + Array.from(msg.int16_values), + originalMsg.int16_values + ); + assert.deepStrictEqual( + Array.from(msg.uint16_values), + originalMsg.uint16_values + ); + assert.deepStrictEqual( + Array.from(msg.int32_values), + originalMsg.int32_values + ); + assert.deepStrictEqual( + Array.from(msg.uint32_values), + originalMsg.uint32_values + ); + assert.deepStrictEqual( + Array.from(msg.int64_values).map((i) => Number(i)), + originalMsg.int64_values + ); + assert.deepStrictEqual( + Array.from(msg.int64_values).map((i) => Number(i)), + originalMsg.uint64_values + ); + assert.deepStrictEqual( + Array.from(msg.string_values), + originalMsg.string_values + ); assert.strictEqual(msg.alignment_check, 0); assert.strictEqual(msg.defaults_values[0].bool_value, true); assert.strictEqual(msg.defaults_values[1].bool_value, true); From dbdd0f0cb831efd5c503ecc4a0a54b36aaf9c6b4 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 15 Dec 2020 17:14:59 +0800 Subject: [PATCH 36/64] fix tests --- rosidl_gen/templates/cppDefinitions.dot | 8 +++----- rosidl_gen/templates/messageRosidl.dot | 4 ---- test/client_setup.js | 2 +- test/publisher_setup.js | 2 +- test/test-array.js | 1 - test/test-interactive.js | 26 ++++++++++++------------- 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 69e5b446..67844025 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -51,15 +51,13 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::WriteRosMessage) { {{? !it.isInternalField(field)}} [&](){ auto js_value = Nan::Get(js_obj, Nan::New("{{=field.name}}").ToLocalChecked()).ToLocalChecked(); -{{? field.default_value !== null}} - if (js_value->IsUndefined()) { + if (js_value->IsNullOrUndefined()) { // default value is initialized when message is created. return; } -{{?}} - {{ +{{ const jsType = it.getJsType(field.type); - }} +}} {{? !field.type.isArray}} {{? field.type.isPrimitiveType}} msg->{{=field.name}} = ToNativeChecked{{=field.name}})>(js_value); diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 9c733ea4..39b71e16 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -269,10 +269,6 @@ class {{=objectWrapper}} { } freeze(own = false, checkConsistency = false) { - if (Object.getOwnPropertyNames(this._proxyObj).length === 0) { - this._rawRos = {{=objectWrapper}}._createRosMessage(); - return; - } this._rawRos = {{=objectWrapper}}._toRosMessage(this._proxyObj); } diff --git a/test/client_setup.js b/test/client_setup.js index 5319efd8..8618bd43 100644 --- a/test/client_setup.js +++ b/test/client_setup.js @@ -30,7 +30,7 @@ rclnodejs var publisher = node.createPublisher(Int8, 'back_add_two_ints'); client.waitForService().then(() => { client.sendRequest(request, (response) => { - publisher.publish(response.sum); + publisher.publish({ data: response.sum }); }); }); diff --git a/test/publisher_setup.js b/test/publisher_setup.js index b8939245..0ed92460 100644 --- a/test/publisher_setup.js +++ b/test/publisher_setup.js @@ -26,7 +26,7 @@ rclnodejs var publisher = node.createPublisher(RclString, 'topic'); var timer = node.createTimer(100, () => { - publisher.publish(msg); + publisher.publish({ data: msg }); }); rclnodejs.spin(node); diff --git a/test/test-array.js b/test/test-array.js index 9f80d427..65214e56 100644 --- a/test/test-array.js +++ b/test/test-array.js @@ -38,7 +38,6 @@ describe('rclnodejs message communication', function () { JointState, 'JointState', (state) => { - console.log(state.position); assert.deepStrictEqual(state.header.stamp.sec, 123456); assert.deepStrictEqual(state.header.stamp.nanosec, 789); assert.deepStrictEqual(state.header.frame_id, 'main frame'); diff --git a/test/test-interactive.js b/test/test-interactive.js index 6a8631b8..4bd91411 100644 --- a/test/test-interactive.js +++ b/test/test-interactive.js @@ -35,22 +35,20 @@ describe('rclnodejs interactive testing', function () { const RclString = 'std_msgs/msg/String'; var publisher = childProcess.fork(`${__dirname}/publisher_setup.js`); var destroy = false; - var subscription = node.createSubscription( - RclString, - 'topic', - function (msg) { - assert.deepStrictEqual(typeof msg, 'object'); - assert.ok('data' in msg); - assert.deepStrictEqual(msg.data, 'Greeting from publisher'); + var subscription = node.createSubscription(RclString, 'topic', function ( + msg + ) { + assert.deepStrictEqual(typeof msg, 'object'); + assert.ok('data' in msg); + assert.deepStrictEqual(msg.data, 'Greeting from publisher'); - if (!destroy) { - publisher.kill('SIGINT'); - node.destroy(); - destroy = true; - done(); - } + if (!destroy) { + publisher.kill('SIGINT'); + node.destroy(); + destroy = true; + done(); } - ); + }); rclnodejs.spin(node); }); }); From b3ec04d879ee02a25321be9f60bceee96432ee00 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 15 Dec 2020 18:19:27 +0800 Subject: [PATCH 37/64] support float typed array --- rosidl_gen/templates/cppDefinitions.dot | 2 +- src/type_conversion.hpp | 52 ++++++++++++++----------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 67844025..4878a944 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -85,7 +85,7 @@ const jsType = it.getJsType(field.type); size_t capacity = {{=field.type.arraySize}}; {{?}} {{? field.type.isPrimitiveType}} - WriteNativeSequence{{=field.name}})>>(js_value, &msg->{{=field.name}}, capacity); + WriteNativeSequence{{=field.name}})>(js_value, &msg->{{=field.name}}, capacity); {{??}} auto typesupport_msg = Nan::To(Nan::Get(typesupport, Nan::New("{{=field.type.pkgName}}/{{=field.type.type}}").ToLocalChecked()).ToLocalChecked()).ToLocalChecked(); WriteNativeObjectSequence{{=field.name}})>>(js_value, &msg->{{=field.name}}, capacity, typesupport_msg); diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 2884dbbc..0e298a7b 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -147,9 +147,19 @@ inline bool IsTypedArray(v8::Local val) { return val->IsBigUint64Array(); } +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsFloat32Array(); +} + +template <> +inline bool IsTypedArray(v8::Local val) { + return val->IsFloat64Array(); +} + template -inline void WriteNativeArrayImpl(v8::Local val, NativeT* arr, - size_t len) { +inline void _WriteNativeArrayImpl(v8::Local val, NativeT* arr, + size_t len) { if (!IsTypedArray(val)) { if (!val->IsArray()) { return; @@ -190,65 +200,61 @@ inline void WriteNativeArray(v8::Local val, T* arr, size_t len) { template <> inline void WriteNativeArray(v8::Local val, int8_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, uint8_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, int16_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, uint16_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, int32_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, uint32_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, int64_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> inline void WriteNativeArray(v8::Local val, uint64_t* arr, size_t len) { - WriteNativeArrayImpl(val, arr, len); + _WriteNativeArrayImpl(val, arr, len); } template <> -inline void WriteNativeArray(v8::Local val, bool* arr, - size_t len) { - if (!val->IsArray()) { - return; - } - auto array = val.As(); - if (array->Length() < len) { - len = array->Length(); - } - for (size_t i = 0; i < len; ++i) { - auto item = Nan::Get(array, i).ToLocalChecked(); - arr[i] = Nan::To(std::move(item)).ToChecked(); - } +inline void WriteNativeArray(v8::Local val, float* arr, + size_t len) { + _WriteNativeArrayImpl(val, arr, len); +} + +template <> +inline void WriteNativeArray(v8::Local val, double* arr, + size_t len) { + _WriteNativeArrayImpl(val, arr, len); } template From 5343b772798ae6e2c82df6dc1caa66e8b7c95498 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 10:17:12 +0800 Subject: [PATCH 38/64] fix tests --- src/type_conversion.hpp | 65 ++------------------- test/test-bounded-sequences.js | 104 ++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 61 deletions(-) diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index 0e298a7b..a06c5b69 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -104,63 +104,10 @@ inline rosidl_runtime_c__U16String ToNativeChecked( return ros_string; } -template -inline bool IsTypedArray(v8::Local val); - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsInt8Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsUint8Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsInt16Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsUint16Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsInt32Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsUint32Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsBigInt64Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsBigUint64Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsFloat32Array(); -} - -template <> -inline bool IsTypedArray(v8::Local val) { - return val->IsFloat64Array(); -} - template inline void _WriteNativeArrayImpl(v8::Local val, NativeT* arr, size_t len) { - if (!IsTypedArray(val)) { + if (!val->IsTypedArray()) { if (!val->IsArray()) { return; } @@ -174,11 +121,11 @@ inline void _WriteNativeArrayImpl(v8::Local val, NativeT* arr, arr[i] = native; } } else { - auto typed_array = val.As(); - if (typed_array->Length() < len) { - len = typed_array->Length(); - } - typed_array->CopyContents(arr, len * sizeof(NativeT)); + auto typed_array = val.As(); + size_t copy_len = typed_array->ByteLength() < len * sizeof(NativeT) + ? typed_array->ByteLength() + : len * sizeof(NativeT); + typed_array->CopyContents(arr, copy_len); } } diff --git a/test/test-bounded-sequences.js b/test/test-bounded-sequences.js index 3bb655ff..88afada2 100644 --- a/test/test-bounded-sequences.js +++ b/test/test-bounded-sequences.js @@ -63,7 +63,7 @@ describe('Test bounded sequeces', function () { const expected = { bool_values: [true, false], byte_values: Uint8Array.from([127, 125]), - char_values: Int8Array.from([127, 125]), + char_values: Int8Array.from([127, 125]), // char[] is uint8_t[] in ROS, the old serialization mistakenly deserialized it as Int8Array float32_values: Float32Array.from([1.1, 2.2, 3.3]), float64_values: Float64Array.from([1.1, 2.2]), int8_values: Int8Array.from([1, 2]), @@ -120,7 +120,107 @@ describe('Test bounded sequeces', function () { 'bounded_sequences', (response) => { clearInterval(timer); - assert.deepEqual(response, expected); + assert.deepStrictEqual(response.bool_values, expected.bool_values); + assert.deepStrictEqual(response.byte_values, expected.byte_values); + assert.deepStrictEqual( + Array.from(response.char_values), + Array.from(expected.char_values) + ); + assert.deepStrictEqual( + response.float32_values, + expected.float32_values + ); + assert.deepStrictEqual( + response.float64_values, + expected.float64_values + ); + assert.deepStrictEqual(response.int8_values, expected.int8_values); + assert.deepStrictEqual(response.uint8_values, expected.uint8_values); + assert.deepStrictEqual(response.int16_values, expected.int16_values); + assert.deepStrictEqual(response.uint16_values, expected.uint16_values); + assert.deepStrictEqual(response.int32_values, expected.int32_values); + assert.deepStrictEqual(response.uint32_values, expected.uint32_values); + assert.deepStrictEqual( + Array.from(response.int64_values).map((i) => Number(i)), + expected.int64_values + ); + assert.deepStrictEqual( + Array.from(response.uint64_values).map((i) => Number(i)), + expected.uint64_values + ); + assert.deepStrictEqual( + Array.from(response.int64_values_default).map((i) => Number(i)), + expected.int64_values_default + ); + assert.deepStrictEqual( + Array.from(response.uint64_values_default).map((i) => Number(i)), + expected.uint64_values_default + ); + assert.deepStrictEqual(response.string_values, expected.string_values); + assert.deepStrictEqual( + response.basic_types_values, + expected.basic_types_values + ); + assert.deepStrictEqual( + response.bool_values_default, + expected.bool_values_default + ); + assert.deepStrictEqual( + response.byte_values_default, + expected.byte_values_default + ); + assert.deepStrictEqual( + Array.from(response.char_values_default), + Array.from(expected.char_values_default) + ); + assert.deepStrictEqual( + response.float32_values_default, + expected.float32_values_default + ); + assert.deepStrictEqual( + response.float64_values_default, + expected.float64_values_default + ); + assert.deepStrictEqual( + response.int16_values_default, + expected.int16_values_default + ); + assert.deepStrictEqual( + response.int32_values_default, + expected.int32_values_default + ); + assert.deepStrictEqual( + response.int8_values_default, + expected.int8_values_default + ); + assert.deepStrictEqual( + response.string_values_default, + expected.string_values_default + ); + assert.deepStrictEqual( + response.uint16_values_default, + expected.uint16_values_default + ); + assert.deepStrictEqual( + response.uint32_values_default, + expected.uint32_values_default + ); + assert.deepStrictEqual( + response.uint8_values_default, + expected.uint8_values_default + ); + assert.deepStrictEqual( + response.alignment_check, + expected.alignment_check + ); + assert.deepStrictEqual( + response.constants_values, + expected.constants_values + ); + assert.deepStrictEqual( + response.defaults_values, + expected.defaults_values + ); node.destroy(); done(); } From 9eb5b5f852109ffd84f7929717c1614df45fa7c8 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 11:00:13 +0800 Subject: [PATCH 39/64] fix tests --- rosidl_gen/templates/cppDefinitions.dot | 2 +- rosidl_gen/templates/messageRosidl.dot | 3 ++- src/type_conversion.hpp | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/rosidl_gen/templates/cppDefinitions.dot b/rosidl_gen/templates/cppDefinitions.dot index 4878a944..46524c63 100644 --- a/rosidl_gen/templates/cppDefinitions.dot +++ b/rosidl_gen/templates/cppDefinitions.dot @@ -133,7 +133,7 @@ NAN_METHOD(rclnodejs__{{=message.structType}}::ToJsObject) { {{?}} {{??}} auto sequence_buffer = Nan::NewBuffer(reinterpret_cast(msg->{{=field.name}}.data), msg->{{=field.name}}.size * sizeof(decltype(*msg->{{=field.name}}.data)), [](char*, void*) {}, nullptr).ToLocalChecked().As(); - Nan::Set(sequence_buffer, Nan::New("_rclnodejs_owner").ToLocalChecked(), info[1]).ToChecked(); + Nan::Set(sequence_buffer->Buffer(), Nan::New("_rclnodejs_owner").ToLocalChecked(), info[1]).ToChecked(); {{? field.type.isPrimitiveType}} Nan::Set(js_obj, Nan::New("{{=field.name}}").ToLocalChecked(), ToJsArrayChecked{{=field.name}}.data)>>(sequence_buffer->Buffer(), 0, msg->{{=field.name}}.size)); {{??}} diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 39b71e16..56907fff 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -233,7 +233,8 @@ class {{=objectWrapper}} { constructor(other) { this._rawRos = undefined; if (other === undefined) { - this._proxyObj = {}; + this._rawRos = {{=objectWrapper}}._createRosMessage(); + this._proxyObj = {{=objectWrapper}}._toJsObject(this._rawRos); } else if (other instanceof {{=objectWrapper}}) { this._proxyObj = other._proxyObj; } else { diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index a06c5b69..bff211b1 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -501,7 +502,7 @@ inline v8::Local ToJsObjectArrayChecked( .ToLocalChecked(); v8::Local argv[1]; for (uint32_t i = 0; i < js_len; ++i) { - argv[0] = v8::Uint8Array::New(buffer, offset, len * sizeof(T)); + argv[0] = v8::Uint8Array::New(buffer, offset + i * sizeof(T), sizeof(T)); auto js_obj = Nan::Call(typesupport_func, Nan::New(), 1, argv) .ToLocalChecked(); Nan::Set(js_array, i, js_obj); From dcbc0d7e32946682f7d6ade74558585afac5f281 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 11:08:02 +0800 Subject: [PATCH 40/64] fix tests --- test/test-disable-typedarray.js | 296 ++++++++++++++++---------------- test/test-multi-nodes.js | 2 +- 2 files changed, 151 insertions(+), 147 deletions(-) diff --git a/test/test-disable-typedarray.js b/test/test-disable-typedarray.js index 11c959b9..42fd76c1 100644 --- a/test/test-disable-typedarray.js +++ b/test/test-disable-typedarray.js @@ -16,184 +16,188 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); +const generatorOptions = require('../generated/generator-options'); /* eslint-disable camelcase */ /* eslint-disable key-spacing */ /* eslint-disable comma-spacing */ -describe('rclnodejs message communication', function () { - this.timeout(60 * 1000); +// rosidl generator only supports typed array +if (generatorOptions.idlProvider !== 'rosidl') { + describe('rclnodejs message communication', function () { + this.timeout(60 * 1000); - before(function () { - return rclnodejs.init(); - }); - - after(function () { - rclnodejs.shutdown(); - }); - - it('disable TypedArray in topic', function (done) { - const msg = { - header: { - stamp: { - sec: 123456, - nanosec: 789, - }, - frame_id: 'main frame', - }, - name: ['Tom', 'Jerry'], - position: [1, 2], - velocity: [2, 3], - effort: [4, 5, 6], - }; - - let node = rclnodejs.createNode('disable_typedarray'); - let timer = setInterval(() => { - let publisher = node.createPublisher( - 'sensor_msgs/msg/JointState', - 'JointState' - ); - assert.doesNotThrow(() => { - publisher.publish(msg); - }, RangeError); - }, 100); + before(function () { + return rclnodejs.init(); + }); - node.createSubscription( - 'sensor_msgs/msg/JointState', - 'JointState', - { enableTypedArray: false }, - (response) => { - clearInterval(timer); - assert.deepStrictEqual(response, msg); - node.destroy(); - done(); - } - ); - rclnodejs.spin(node); - }); + after(function () { + rclnodejs.shutdown(); + }); - it('disable TypedArray in response', function (done) { - const mapData = { - map: { + it('disable TypedArray in topic', function (done) { + const msg = { header: { stamp: { sec: 123456, nanosec: 789, }, - frame_id: 'main_frame', + frame_id: 'main frame', }, - info: { - map_load_time: { - sec: 123456, - nanosec: 789, + name: ['Tom', 'Jerry'], + position: [1, 2], + velocity: [2, 3], + effort: [4, 5, 6], + }; + + let node = rclnodejs.createNode('disable_typedarray'); + let timer = setInterval(() => { + let publisher = node.createPublisher( + 'sensor_msgs/msg/JointState', + 'JointState' + ); + assert.doesNotThrow(() => { + publisher.publish(msg); + }, RangeError); + }, 100); + + node.createSubscription( + 'sensor_msgs/msg/JointState', + 'JointState', + { enableTypedArray: false }, + (response) => { + clearInterval(timer); + assert.deepStrictEqual(response, msg); + node.destroy(); + done(); + } + ); + rclnodejs.spin(node); + }); + + it('disable TypedArray in response', function (done) { + const mapData = { + map: { + header: { + stamp: { + sec: 123456, + nanosec: 789, + }, + frame_id: 'main_frame', }, - resolution: 1.0, - width: 1024, - height: 768, - origin: { - position: { - x: 0.0, - y: 0.0, - z: 0.0, + info: { + map_load_time: { + sec: 123456, + nanosec: 789, }, - orientation: { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, + resolution: 1.0, + width: 1024, + height: 768, + origin: { + position: { + x: 0.0, + y: 0.0, + z: 0.0, + }, + orientation: { + x: 0.0, + y: 0.0, + z: 0.0, + w: 0.0, + }, }, }, + data: [1, 2, 3], }, - data: [1, 2, 3], - }, - }; - const node = rclnodejs.createNode('disable_typedarray'); + }; + const node = rclnodejs.createNode('disable_typedarray'); - node.createService('nav_msgs/srv/GetMap', 'get_map', () => { - return mapData; - }); + node.createService('nav_msgs/srv/GetMap', 'get_map', () => { + return mapData; + }); - rclnodejs.spin(node); - const client = node.createClient('nav_msgs/srv/GetMap', 'get_map', { - enableTypedArray: false, - }); - client.sendRequest({}, (response) => { - assert.deepStrictEqual(response, mapData); - node.destroy(); - done(); + rclnodejs.spin(node); + const client = node.createClient('nav_msgs/srv/GetMap', 'get_map', { + enableTypedArray: false, + }); + client.sendRequest({}, (response) => { + assert.deepStrictEqual(response, mapData); + node.destroy(); + done(); + }); }); - }); - it('disable TypedArray in request', function (done) { - const mapData = { - map: { - header: { - stamp: { - sec: 123456, - nanosec: 789, - }, - frame_id: 'main_frame', - }, - info: { - map_load_time: { - sec: 123456, - nanosec: 789, + it('disable TypedArray in request', function (done) { + const mapData = { + map: { + header: { + stamp: { + sec: 123456, + nanosec: 789, + }, + frame_id: 'main_frame', }, - resolution: 1.0, - width: 1024, - height: 768, - origin: { - position: { - x: 0.0, - y: 0.0, - z: 0.0, + info: { + map_load_time: { + sec: 123456, + nanosec: 789, }, - orientation: { - x: 0.0, - y: 0.0, - z: 0.0, - w: 0.0, + resolution: 1.0, + width: 1024, + height: 768, + origin: { + position: { + x: 0.0, + y: 0.0, + z: 0.0, + }, + orientation: { + x: 0.0, + y: 0.0, + z: 0.0, + w: 0.0, + }, }, }, + data: [1, 2, 3], }, - data: [1, 2, 3], - }, - initial_pose: { - header: { - stamp: { - sec: 123456, - nanosec: 789, + initial_pose: { + header: { + stamp: { + sec: 123456, + nanosec: 789, + }, + frame_id: 'main frame', }, - frame_id: 'main frame', - }, - pose: { pose: { - position: { x: 11.5, y: 112.75, z: 9.0 }, - orientation: { x: 31.5, y: 21.5, z: 7.5, w: 1.5 }, + pose: { + position: { x: 11.5, y: 112.75, z: 9.0 }, + orientation: { x: 31.5, y: 21.5, z: 7.5, w: 1.5 }, + }, + covariance: Array.from({ length: 36 }, (v, k) => k), }, - covariance: Array.from({ length: 36 }, (v, k) => k), }, - }, - }; + }; - const node = rclnodejs.createNode('array_client'); - node.createService( - 'nav_msgs/srv/SetMap', - 'set_map', - { enableTypedArray: false }, - (request, response) => { - assert.deepStrictEqual(request, mapData); - let result = response.template; - result.success = true; - response.send(result); - } - ); + const node = rclnodejs.createNode('array_client'); + node.createService( + 'nav_msgs/srv/SetMap', + 'set_map', + { enableTypedArray: false }, + (request, response) => { + assert.deepStrictEqual(request, mapData); + let result = response.template; + result.success = true; + response.send(result); + } + ); - rclnodejs.spin(node); - const client = node.createClient('nav_msgs/srv/SetMap', 'set_map'); - client.sendRequest(mapData, (response) => { - assert.deepStrictEqual(response.success, true); - node.destroy(); - done(); + rclnodejs.spin(node); + const client = node.createClient('nav_msgs/srv/SetMap', 'set_map'); + client.sendRequest(mapData, (response) => { + assert.deepStrictEqual(response.success, true); + node.destroy(); + done(); + }); }); }); -}); +} diff --git a/test/test-multi-nodes.js b/test/test-multi-nodes.js index 8bd7c52f..a5e994a0 100644 --- a/test/test-multi-nodes.js +++ b/test/test-multi-nodes.js @@ -69,7 +69,7 @@ describe('Multiple nodes interation testing', function () { ); var jsPublisher = node.createPublisher(RclString, 'js_pycpp_chatter'); setTimeout(() => { - jsPublisher.publish(msg); + jsPublisher.publish({ data: msg }); }, 1000); rclnodejs.spin(node); }); From 6754715bea24476816c1e6ede2e7add9dbc03117 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 11:11:36 +0800 Subject: [PATCH 41/64] fix tests --- test/test-cross-lang.js | 4 ++-- test/test-lifecycle-publisher.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test-cross-lang.js b/test/test-cross-lang.js index 1a63f289..307b79da 100644 --- a/test/test-cross-lang.js +++ b/test/test-cross-lang.js @@ -106,7 +106,7 @@ describe('Cross-language interaction', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + publisher.publish({ data: msg }); }); rclnodejs.spin(node); }); @@ -135,7 +135,7 @@ describe('Cross-language interaction', function () { var msg = text; var timer = node.createTimer(100, () => { - publisher.publish(msg); + publisher.publish({ data: msg }); }); rclnodejs.spin(node); diff --git a/test/test-lifecycle-publisher.js b/test/test-lifecycle-publisher.js index 688e1e9f..ab0e86d3 100644 --- a/test/test-lifecycle-publisher.js +++ b/test/test-lifecycle-publisher.js @@ -97,22 +97,22 @@ describe('LifecyclePublisher test suite', function () { } ); - lifecyclePublisher.publish(TEST_MSG); + lifecyclePublisher.publish({ data: TEST_MSG }); await assertUtils.createDelay(waitTime); assert.strictEqual(cbCnt, 0); lifecyclePublisher.activate(); - lifecyclePublisher.publish(TEST_MSG); + lifecyclePublisher.publish({ data: TEST_MSG }); await assertUtils.createDelay(waitTime); assert.strictEqual(cbCnt, 1); lifecyclePublisher.deactivate(); - lifecyclePublisher.publish(TEST_MSG); + lifecyclePublisher.publish({ data: TEST_MSG }); await assertUtils.createDelay(waitTime); assert.strictEqual(cbCnt, 1); lifecyclePublisher.activate(); - lifecyclePublisher.publish(TEST_MSG); + lifecyclePublisher.publish({ data: TEST_MSG }); await assertUtils.createDelay(waitTime); assert.strictEqual(cbCnt, 2); }); From 9e8cf57ac583c4fb1be41583f82cac66ae74b546 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 11:44:13 +0800 Subject: [PATCH 42/64] fix tests --- test/test-cross-lang.js | 13 +++- test/test-message-translator-primitive.js | 9 ++- test/test-message-type.js | 2 +- test/test-msg-type-cpp-node.js | 85 +++++++++++++++++++---- test/test-msg-type-py-node.js | 85 +++++++++++++++++++---- test/test-multi-nodes.js | 7 +- test/test-single-process.js | 7 +- 7 files changed, 173 insertions(+), 35 deletions(-) diff --git a/test/test-cross-lang.js b/test/test-cross-lang.js index 307b79da..786d87e3 100644 --- a/test/test-cross-lang.js +++ b/test/test-cross-lang.js @@ -20,6 +20,7 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); +const generatorOptions = require('../generated/generator-options'); describe('Cross-language interaction', function () { this.timeout(60 * 1000); @@ -106,7 +107,11 @@ describe('Cross-language interaction', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish({ data: msg }); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -135,7 +140,11 @@ describe('Cross-language interaction', function () { var msg = text; var timer = node.createTimer(100, () => { - publisher.publish({ data: msg }); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); diff --git a/test/test-message-translator-primitive.js b/test/test-message-translator-primitive.js index 66c26010..6ee01005 100644 --- a/test/test-message-translator-primitive.js +++ b/test/test-message-translator-primitive.js @@ -17,6 +17,7 @@ const rclnodejs = require('../index.js'); const deepEqual = require('deep-equal'); const arrayGen = require('./array_generator.js'); +const generatorOptions = require('../generated/generator-options'); /* eslint-disable camelcase */ /* eslint-disable indent */ @@ -35,7 +36,7 @@ describe('Rclnodejs message translation: primitive types', function () { [ { type: 'Bool', values: [true, false] }, { type: 'Byte', values: [0, 1, 2, 3, 255] }, - { type: 'Char', values: [-128, -127, -2, -1, 0, 1, 2, 3, 127] }, + { type: 'Char', values: [0, 1, 2, 3, 127, 128, 255] }, // char is unsigned in ROS { type: 'Float32', values: [-5, 0, 1.25, 89.75, 72.5, 3.14e5] }, { type: 'Float64', values: [-5, 0, 1.25, 89.75, 72.5, 3.14159265358e8] }, { type: 'Int16', values: [-32768, -2, -1, 0, 1, 2, 3, 32767] }, @@ -103,7 +104,11 @@ describe('Rclnodejs message translation: primitive types', function () { ); } }); - publisher.publish(v); // Short-cut form of publishing primitive types + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: v }); // Short-cut form not supported in rosidl generator + } else { + publisher.publish(v); // Short-cut form of publishing primitive types + } rclnodejs.spin(node); }); } diff --git a/test/test-message-type.js b/test/test-message-type.js index 5034a35e..730588de 100644 --- a/test/test-message-type.js +++ b/test/test-message-type.js @@ -71,7 +71,7 @@ describe('Rclnodejs message type testing', function () { const msgChar = 'std_msgs/msg/Char'; var publisher = childProcess.fork(`${__dirname}/publisher_msg.js`, [ 'Char', - '"A"', + '65', // char in uint8 in ROS ]); var subscription = node.createSubscription( msgChar, diff --git a/test/test-msg-type-cpp-node.js b/test/test-msg-type-cpp-node.js index 09bfa1c0..938301a9 100644 --- a/test/test-msg-type-cpp-node.js +++ b/test/test-msg-type-cpp-node.js @@ -22,6 +22,7 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); +const generatorOptions = require('../generated/generator-options'); describe('Rclnodejs - Cpp message type testing', function () { var cppSubscriptionPath = path.join(__dirname, 'cpp', 'subscription_msg'); @@ -59,7 +60,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -83,7 +88,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -107,7 +116,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -131,7 +144,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -156,7 +173,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -180,7 +201,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -204,7 +229,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -228,7 +257,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -252,7 +285,11 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -275,7 +312,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -298,7 +339,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -322,7 +367,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -345,7 +394,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -368,7 +421,11 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); diff --git a/test/test-msg-type-py-node.js b/test/test-msg-type-py-node.js index 8bbc93c6..5cfbbb45 100644 --- a/test/test-msg-type-py-node.js +++ b/test/test-msg-type-py-node.js @@ -21,6 +21,7 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); +const generatorOptions = require('../generated/generator-options'); describe('Rclnodejs - Python message type testing', function () { this.timeout(60 * 1000); @@ -59,7 +60,15 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -87,7 +96,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + publisher.publish({ data: msg.charCodeAt(0) }); }); rclnodejs.spin(node); }); @@ -115,7 +124,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -143,7 +156,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -171,7 +188,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -199,7 +220,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -227,7 +252,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -255,7 +284,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -283,7 +316,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -311,7 +348,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -339,7 +380,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -367,7 +412,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -395,7 +444,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); @@ -423,7 +476,11 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - publisher.publish(msg); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(node); }); diff --git a/test/test-multi-nodes.js b/test/test-multi-nodes.js index a5e994a0..cc0d3997 100644 --- a/test/test-multi-nodes.js +++ b/test/test-multi-nodes.js @@ -20,6 +20,7 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); +const generatorOptions = require('../generated/generator-options'); describe('Multiple nodes interation testing', function () { this.timeout(60 * 1000); @@ -69,7 +70,11 @@ describe('Multiple nodes interation testing', function () { ); var jsPublisher = node.createPublisher(RclString, 'js_pycpp_chatter'); setTimeout(() => { - jsPublisher.publish({ data: msg }); + if (generatorOptions.idlProvider === 'rosidl') { + jsPublisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + jsPublisher.publish(msg); + } }, 1000); rclnodejs.spin(node); }); diff --git a/test/test-single-process.js b/test/test-single-process.js index 6ee22d8b..e6ff1c38 100644 --- a/test/test-single-process.js +++ b/test/test-single-process.js @@ -16,6 +16,7 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); +const generatorOptions = require('../generated/generator-options'); describe('Test rclnodejs nodes in a single process', function () { this.timeout(60 * 1000); @@ -51,7 +52,11 @@ describe('Test rclnodejs nodes in a single process', function () { 'single_ps_channel1' ); var timer = publisherNode.createTimer(100, () => { - publisher.publish({ data: msg }); + if (generatorOptions.idlProvider === 'rosidl') { + publisher.publish({ data: msg }); // short form not supported by rosidl generator + } else { + publisher.publish(msg); + } }); rclnodejs.spin(subscriptionNode); rclnodejs.spin(publisherNode); From 3dc6f4fd2d996a230dfbd6d89f82bb78240eb284 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 12:15:49 +0800 Subject: [PATCH 43/64] remove postinstalls script --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e332cd6a..399f0b24 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "test": "node ./scripts/compile_tests.js && node --expose-gc ./scripts/run_test.js && npm run dtslint", "dtslint": "node ./scripts/generate_tsd.js && dtslint test/types", "lint": "eslint --max-warnings=0 --ext js,ts index.js types scripts lib example rosidl_gen rosidl_parser test benchmark/rclnodejs && node ./scripts/cpplint.js", - "postinstall": "node scripts/generate_messages.js", "format": "clang-format -i -style=file ./src/*.cpp ./src/*.hpp && prettier --write \"{lib,rosidl_gen,rostsd_gen,rosidl_parser,types,example,test,scripts,benchmark}/**/*.{js,md,ts}\" ./*.{js,md,ts}" }, "authors": [ From 4aac6a0f1770ad7c14dd75ce61db49f8132e8030 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 16 Dec 2020 12:43:15 +0800 Subject: [PATCH 44/64] cleanup --- rosidl_gen/templates/messageRosidl.dot | 88 +------------------------- 1 file changed, 1 insertion(+), 87 deletions(-) diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 56907fff..ac92dc9d 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -7,11 +7,7 @@ {{ let objectWrapper = it.spec.msgName + 'Wrapper'; -let arrayWrapper = it.spec.msgName + 'ArrayWrapper'; -let refObjectType = it.spec.msgName + 'RefStruct'; -let refObjectArrayType = it.spec.msgName + 'RefStructArray'; -let refArrayType = it.spec.msgName + 'RefArray'; const compactMsgDefJSON = JSON.stringify(JSON.parse(it.json)); if (it.spec.fields.length === 0) { @@ -67,82 +63,8 @@ function getPrimitiveNameByType(type) { } } -function getTypedArrayName(type) { - const t = type.type.toLowerCase(); - let typedArrayName; - - switch (t) { - case 'byte': - case 'octet': - case 'uint8': - typedArrayName = 'Uint8Array'; - break; - case 'char': - case 'int8': - typedArrayName = 'Int8Array'; - break; - case 'int16': - case 'short': - typedArrayName = 'Int16Array'; - break; - case 'uint16': - case 'unsigned short': - typedArrayName = 'Uint16Array'; - break; - case 'int32': - case 'long': - typedArrayName = 'Int32Array'; - break; - case 'uint32': - case 'unsigned long': - typedArrayName = 'Uint32Array'; - break; - case 'float': - case 'float32': - typedArrayName = 'Float32Array'; - break; - case 'double': - case 'float64': - typedArrayName = 'Float64Array'; - break; - default: - typedArrayName = ''; - } - - return typedArrayName; -} - -function getTypedArrayElementName(type) { - const t = type.type.toLowerCase(); - if (t === 'int8') { - return 'int8'; - } else if (t === 'uint8') { - return 'uint8'; - } else if (t === 'int16') { - return 'int16'; - } else if (t === 'uint16') { - return 'uint16'; - } else if (t === 'int32') { - return 'int32'; - } else if (t === 'uint32') { - return 'uint32'; - } else if (t === 'float64') { - return 'double'; - } else if (t === 'float32') { - return 'float'; - } else if (t === 'char') { - return 'int8'; - } else if (t === 'byte') { - return 'uint8'; - } else { - return ''; - } -} - const primitiveBaseType = ['Bool', 'Int8', 'UInt8', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64', 'Float64', 'Float32', 'Char', 'Byte', 'String']; -const typedArrayType = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', - 'float64', 'float32', 'char', 'byte']; let existedModules = []; @@ -154,17 +76,9 @@ function isPrimitivePackage(baseType) { return primitiveBaseType.indexOf(baseType.type) !== -1; } -function isTypedArrayType(type) { - return typedArrayType.indexOf(type.type.toLowerCase()) !== -1; -} - -const usePlainTypedArray = isTypedArrayType(it.spec.baseType); -const currentTypedArray = getTypedArrayName(it.spec.baseType); -const currentTypedArrayElementType = getTypedArrayElementName(it.spec.baseType); - function shouldRequire(baseType, fieldType) { let requiredModule = '{{=getPackageNameByType(fieldType)}}/{{=getModulePathByType(fieldType)}}'; - let shouldRequire = !isPrimitivePackage(baseType) && !fieldType.isPrimitiveType; + let shouldRequire = !fieldType.isPrimitiveType; if (shouldRequire && !isExisted(requiredModule)) { existedModules.push(requiredModule); From 674a32cd15295aa7a1293b38df512eff658598e9 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 7 Jan 2021 16:22:53 +0800 Subject: [PATCH 45/64] allow runtime message generation --- binding.gyp | 5 +- package.json | 3 +- rosidl_gen/idl_generator.js | 7 +- rosidl_gen/index.js | 30 +++++-- rosidl_gen/templates/messageRosidl.dot | 2 +- rosidl_gen/templates/typesupportGyp.dot | 103 +++++++++++++++++++++++ rosidl_gen/templates/typesupportGypi.dot | 19 ----- 7 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 rosidl_gen/templates/typesupportGyp.dot delete mode 100644 rosidl_gen/templates/typesupportGypi.dot diff --git a/binding.gyp b/binding.gyp index fe69e337..70324ece 100644 --- a/binding.gyp +++ b/binding.gyp @@ -146,8 +146,5 @@ ] ] } - ], - 'includes': [ - 'src/generated/typesupport.gypi', - ], + ] } diff --git a/package.json b/package.json index 399f0b24..36d840d3 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "typescript" ], "scripts": { - "install": "node scripts/generate_messages.js && node scripts/build.js", + "install": "node scripts/build.js && node scripts/generate_messages.js", "docs": "cd docs && make", "test": "node ./scripts/compile_tests.js && node --expose-gc ./scripts/run_test.js && npm run dtslint", "dtslint": "node ./scripts/generate_tsd.js && dtslint test/types", @@ -44,6 +44,7 @@ "husky": "^4.2.5", "lint-staged": "^10.2.11", "mocha": "^8.0.1", + "node-gyp": "^7.1.2", "prettier": "^2.0.5", "sinon": "^9.0.2", "tree-kill": "^1.2.2", diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 2f351910..ae315329 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -578,11 +578,8 @@ async function generateTypesupportGypi(pkgsEntries, rosIdlDb, options) { dependencies: await rosIdlDb.getDependentPackages(pkgName), })) ); - const rendered = removeEmptyLines(dots.typesupportGypi({ pkgs })); - await fs.writeFile( - path.join('src', 'generated', 'typesupport.gypi'), - rendered - ); + const rendered = removeEmptyLines(dots.typesupportGyp({ pkgs })); + await fs.writeFile(path.join('src', 'generated', 'binding.gyp'), rendered); } module.exports = { diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 8cc53241..8fb56a4b 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -14,14 +14,16 @@ 'use strict'; +const child_process = require('child_process'); const fsp = require('fs').promises; const fse = require('fs-extra'); const { RosIdlDb, generateJSStructFromIDL, generateCppDefinitions, - generateTypesupportGypi, + generateTypesupportGypi: generateTypesupportGyp, } = require('./idl_generator.js'); +const os = require('os'); const packages = require('./packages.js'); const path = require('path'); @@ -52,12 +54,26 @@ async function generateInPaths(paths, options) { ) ); - await Promise.all( - pkgsEntries.map(([pkgName, pkgInfo]) => - generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) - ) - ); - await generateTypesupportGypi(pkgsEntries, rosIdlDb, options); + if (options.idlProvider === 'rosidl') { + await Promise.all( + pkgsEntries.map(([pkgName, pkgInfo]) => + generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) + ) + ); + await generateTypesupportGyp(pkgsEntries, rosIdlDb, options); + await child_process.spawn( + 'node', + [`${__dirname}/../node_modules/.bin/node-gyp`, 'rebuild'], + { + cwd: `${__dirname}/../src/generated`, + stdio: 'inherit', + env: { + ...process.env, + JOBS: os.cpus().length, + }, + } + ); + } } async function generateAll(forcedGenerating) { diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index ac92dc9d..f639a370 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -130,7 +130,7 @@ function extractMemberNames(fields) { } }} -const typesupport = require('bindings')('{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; +const typesupport = require('../../src/generated/build/Release/{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; const typesupportDeps = {}; {{~ it.spec.fields :field}} diff --git a/rosidl_gen/templates/typesupportGyp.dot b/rosidl_gen/templates/typesupportGyp.dot new file mode 100644 index 00000000..13c88452 --- /dev/null +++ b/rosidl_gen/templates/typesupportGyp.dot @@ -0,0 +1,103 @@ +{ + 'target_defaults': { + 'default_configuration': 'Release', + 'configurations': { + 'Debug': { + 'defines': ['DEBUG_ON'], + }, + } + }, + 'target_defaults': { + 'include_dirs': [ + " Date: Thu, 7 Jan 2021 16:28:17 +0800 Subject: [PATCH 46/64] replace generatorOptions tests with process.env tests --- test/test-cross-lang.js | 5 ++-- test/test-disable-typedarray.js | 3 +-- test/test-message-translator-primitive.js | 3 +-- test/test-msg-type-cpp-node.js | 29 ++++++++++---------- test/test-msg-type-py-node.js | 33 ++++++++++------------- test/test-multi-nodes.js | 3 +-- test/test-single-process.js | 3 +-- 7 files changed, 34 insertions(+), 45 deletions(-) diff --git a/test/test-cross-lang.js b/test/test-cross-lang.js index 786d87e3..3225c538 100644 --- a/test/test-cross-lang.js +++ b/test/test-cross-lang.js @@ -20,7 +20,6 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); -const generatorOptions = require('../generated/generator-options'); describe('Cross-language interaction', function () { this.timeout(60 * 1000); @@ -107,7 +106,7 @@ describe('Cross-language interaction', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -140,7 +139,7 @@ describe('Cross-language interaction', function () { var msg = text; var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-disable-typedarray.js b/test/test-disable-typedarray.js index 42fd76c1..6ac3deae 100644 --- a/test/test-disable-typedarray.js +++ b/test/test-disable-typedarray.js @@ -16,13 +16,12 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); -const generatorOptions = require('../generated/generator-options'); /* eslint-disable camelcase */ /* eslint-disable key-spacing */ /* eslint-disable comma-spacing */ // rosidl generator only supports typed array -if (generatorOptions.idlProvider !== 'rosidl') { +if (process.env.RCLNODEJS_USE_ROSIDL) { describe('rclnodejs message communication', function () { this.timeout(60 * 1000); diff --git a/test/test-message-translator-primitive.js b/test/test-message-translator-primitive.js index 6ee01005..c41261e9 100644 --- a/test/test-message-translator-primitive.js +++ b/test/test-message-translator-primitive.js @@ -17,7 +17,6 @@ const rclnodejs = require('../index.js'); const deepEqual = require('deep-equal'); const arrayGen = require('./array_generator.js'); -const generatorOptions = require('../generated/generator-options'); /* eslint-disable camelcase */ /* eslint-disable indent */ @@ -104,7 +103,7 @@ describe('Rclnodejs message translation: primitive types', function () { ); } }); - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: v }); // Short-cut form not supported in rosidl generator } else { publisher.publish(v); // Short-cut form of publishing primitive types diff --git a/test/test-msg-type-cpp-node.js b/test/test-msg-type-cpp-node.js index 938301a9..3cd56f59 100644 --- a/test/test-msg-type-cpp-node.js +++ b/test/test-msg-type-cpp-node.js @@ -22,7 +22,6 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); -const generatorOptions = require('../generated/generator-options'); describe('Rclnodejs - Cpp message type testing', function () { var cppSubscriptionPath = path.join(__dirname, 'cpp', 'subscription_msg'); @@ -60,7 +59,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -88,7 +87,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -116,7 +115,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -144,7 +143,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -173,7 +172,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -201,7 +200,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -229,7 +228,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -257,7 +256,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -285,7 +284,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -312,7 +311,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -339,7 +338,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -367,7 +366,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -394,7 +393,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -421,7 +420,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-msg-type-py-node.js b/test/test-msg-type-py-node.js index 5cfbbb45..fde56e37 100644 --- a/test/test-msg-type-py-node.js +++ b/test/test-msg-type-py-node.js @@ -21,7 +21,6 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); -const generatorOptions = require('../generated/generator-options'); describe('Rclnodejs - Python message type testing', function () { this.timeout(60 * 1000); @@ -60,12 +59,8 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { - if (generatorOptions.idlProvider === 'rosidl') { - publisher.publish({ data: msg }); // short form not supported by rosidl generator - } else { - publisher.publish(msg); - } // short form not supported by rosidl generator + if (process.env.RCLNODEJS_USE_ROSIDL) { + publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); } @@ -124,7 +119,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -156,7 +151,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -188,7 +183,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -220,7 +215,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -252,7 +247,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -284,7 +279,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -316,7 +311,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -348,7 +343,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -380,7 +375,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -412,7 +407,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -444,7 +439,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -476,7 +471,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-multi-nodes.js b/test/test-multi-nodes.js index cc0d3997..a317898d 100644 --- a/test/test-multi-nodes.js +++ b/test/test-multi-nodes.js @@ -20,7 +20,6 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); -const generatorOptions = require('../generated/generator-options'); describe('Multiple nodes interation testing', function () { this.timeout(60 * 1000); @@ -70,7 +69,7 @@ describe('Multiple nodes interation testing', function () { ); var jsPublisher = node.createPublisher(RclString, 'js_pycpp_chatter'); setTimeout(() => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { jsPublisher.publish({ data: msg }); // short form not supported by rosidl generator } else { jsPublisher.publish(msg); diff --git a/test/test-single-process.js b/test/test-single-process.js index e6ff1c38..3e018b3a 100644 --- a/test/test-single-process.js +++ b/test/test-single-process.js @@ -16,7 +16,6 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); -const generatorOptions = require('../generated/generator-options'); describe('Test rclnodejs nodes in a single process', function () { this.timeout(60 * 1000); @@ -52,7 +51,7 @@ describe('Test rclnodejs nodes in a single process', function () { 'single_ps_channel1' ); var timer = publisherNode.createTimer(100, () => { - if (generatorOptions.idlProvider === 'rosidl') { + if (process.env.RCLNODEJS_USE_ROSIDL) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); From 1fcf56988e205c6112de7cef5201d2fdfdbcb32f Mon Sep 17 00:00:00 2001 From: koonpeng Date: Thu, 7 Jan 2021 18:05:56 +0800 Subject: [PATCH 47/64] various fixes, skipping unrelated tests --- rosidl_gen/index.js | 8 +- rosidl_gen/message_translator.js | 1 + rosidl_gen/templates/messageRosidl.dot | 2 +- test/test-array-data.js | 1064 ++++++++++++------------ test/test-compound-msg-type-check.js | 30 +- test/test-disable-typedarray.js | 2 +- 6 files changed, 573 insertions(+), 534 deletions(-) diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 8fb56a4b..3c66ab3c 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -42,6 +42,8 @@ async function generateInPaths(paths, options) { pkgs.set(pkgName, { ...pkgInfo, amentRoot: paths[i] }); } }); + // skip this package as it contains message that is invalid + pkgs.delete('libstatistics_collector'); const rosIdlDb = new RosIdlDb(pkgs); @@ -56,9 +58,9 @@ async function generateInPaths(paths, options) { if (options.idlProvider === 'rosidl') { await Promise.all( - pkgsEntries.map(([pkgName, pkgInfo]) => - generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) - ) + pkgsEntries.map(([pkgName, pkgInfo]) => { + generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options); + }) ); await generateTypesupportGyp(pkgsEntries, rosIdlDb, options); await child_process.spawn( diff --git a/rosidl_gen/message_translator.js b/rosidl_gen/message_translator.js index 647d72ff..7d94b0d4 100644 --- a/rosidl_gen/message_translator.js +++ b/rosidl_gen/message_translator.js @@ -49,6 +49,7 @@ function copyMsgObject(msg, obj) { } } else { // Proceed further of this object + console.log(i, msg[i]); copyMsgObject(msg[i], obj[i]); } } else { diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index f639a370..18cc65fe 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -148,7 +148,7 @@ class {{=objectWrapper}} { this._rawRos = undefined; if (other === undefined) { this._rawRos = {{=objectWrapper}}._createRosMessage(); - this._proxyObj = {{=objectWrapper}}._toJsObject(this._rawRos); + this._proxyObj = {}; } else if (other instanceof {{=objectWrapper}}) { this._proxyObj = other._proxyObj; } else { diff --git a/test/test-array-data.js b/test/test-array-data.js index 85d56812..df481d87 100644 --- a/test/test-array-data.js +++ b/test/test-array-data.js @@ -48,160 +48,183 @@ describe('rclnodejs message communication', function () { data_offset: 0, }; - [ - { - pkg: 'std_msgs', - type: 'Int8MultiArray', - values: [ - { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array - { layout: layout, data: Int8Array.from([-10, 1, 2, 3, 8, 6, 0, -25]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'Int16MultiArray', - values: [ - { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array - { layout: layout, data: Int16Array.from([-10, 1, 2, 3, 8, 6, 0, -25]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'Int32MultiArray', - values: [ - { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array - { layout: layout, data: Int32Array.from([-10, 1, 2, 3, 8, 6, 0, -25]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'Int64MultiArray', - values: [ - { - layout: layout, - data: [-111, 1, 2, 3, 8, 6, 0, -25, Number.MAX_SAFE_INTEGER], - }, // Provide data via Array - ], - }, - { - pkg: 'std_msgs', - type: 'ByteMultiArray', - values: [ - { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array - { layout: layout, data: Uint8Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'UInt8MultiArray', - values: [ - { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array - { layout: layout, data: Uint8Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'UInt16MultiArray', - values: [ - { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array - { layout: layout, data: Uint16Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'UInt32MultiArray', - values: [ - { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array - { layout: layout, data: Uint32Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'UInt64MultiArray', - values: [ - { - layout: layout, - data: [0, 1, 2, 3, 8, 6, 0, 255, Number.MAX_SAFE_INTEGER], - }, // Provide data via Array - ], - }, - { - pkg: 'std_msgs', - type: 'Float32MultiArray', - values: [ - { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array - { - layout: layout, - data: Float32Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), - }, // Provide data via TypedArray - ], - }, - { - pkg: 'std_msgs', - type: 'Float64MultiArray', - values: [ - { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array - { - layout: layout, - data: Float64Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), - }, // Provide data via TypedArray - ], - }, - /* eslint-enable camelcase */ - /* eslint-enable key-spacing */ - /* eslint-enable comma-spacing */ - ].forEach((testData) => { - const topic = testData.topic || 'topic' + testData.type; - testData.values.forEach((v, i) => { - it('Test ' + testData.type + '.copy()' + ', case ' + i, function () { - const MessageType = rclnodejs.require( - testData.pkg + '/msg/' + testData.type - ); - const msg1 = translator.toROSMessage(MessageType, v); - const msg2 = new MessageType(); - msg2.copy(msg1); + // Unlike the old bindings, the new rosidl bindings does not use a message translator. + // Messages are just plain js objects until serialization, a side effect is that there + // is no "zero initialization" at message creation time. It causes this test to fail + // because it depends on being able to introspect the message by recursively calling + // each fields .hasMember function. This test is also not really needed as there is no + // logic in the .copy method in the new bindings. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + [ + { + pkg: 'std_msgs', + type: 'Int8MultiArray', + values: [ + { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array + { + layout: layout, + data: Int8Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'Int16MultiArray', + values: [ + { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array + { + layout: layout, + data: Int16Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'Int32MultiArray', + values: [ + { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array + { + layout: layout, + data: Int32Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'Int64MultiArray', + values: [ + { + layout: layout, + data: [-111, 1, 2, 3, 8, 6, 0, -25, Number.MAX_SAFE_INTEGER], + }, // Provide data via Array + ], + }, + { + pkg: 'std_msgs', + type: 'ByteMultiArray', + values: [ + { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array + { layout: layout, data: Uint8Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'UInt8MultiArray', + values: [ + { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array + { layout: layout, data: Uint8Array.from([0, 1, 2, 3, 8, 6, 0, 255]) }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'UInt16MultiArray', + values: [ + { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array + { + layout: layout, + data: Uint16Array.from([0, 1, 2, 3, 8, 6, 0, 255]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'UInt32MultiArray', + values: [ + { layout: layout, data: [0, 1, 2, 3, 8, 6, 0, 255] }, // Provide data via Array + { + layout: layout, + data: Uint32Array.from([0, 1, 2, 3, 8, 6, 0, 255]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'UInt64MultiArray', + values: [ + { + layout: layout, + data: [0, 1, 2, 3, 8, 6, 0, 255, Number.MAX_SAFE_INTEGER], + }, // Provide data via Array + ], + }, + { + pkg: 'std_msgs', + type: 'Float32MultiArray', + values: [ + { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array + { + layout: layout, + data: Float32Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), + }, // Provide data via TypedArray + ], + }, + { + pkg: 'std_msgs', + type: 'Float64MultiArray', + values: [ + { layout: layout, data: [-10, 1, 2, 3, 8, 6, 0, -25] }, // Provide data via Array + { + layout: layout, + data: Float64Array.from([-10, 1, 2, 3, 8, 6, 0, -25]), + }, // Provide data via TypedArray + ], + }, + /* eslint-enable camelcase */ + /* eslint-enable key-spacing */ + /* eslint-enable comma-spacing */ + ].forEach((testData) => { + const topic = testData.topic || 'topic' + testData.type; + testData.values.forEach((v, i) => { + it('Test ' + testData.type + '.copy()' + ', case ' + i, function () { + const MessageType = rclnodejs.require( + testData.pkg + '/msg/' + testData.type + ); + const msg1 = translator.toROSMessage(MessageType, v); + const msg2 = new MessageType(); + msg2.copy(msg1); - function checkMessage(msg) { - assert(typeof msg.layout === 'object'); + function checkMessage(msg) { + assert(typeof msg.layout === 'object'); - assert(Array.isArray(msg.layout.dim.data)); - // First element - assert(typeof msg.layout.dim.data[0] === 'object'); - assert(msg.layout.dim.data[0].label === v.layout.dim[0].label); - assert(msg.layout.dim.data[0].size === v.layout.dim[0].size); - assert(msg.layout.dim.data[0].stride === v.layout.dim[0].stride); + assert(Array.isArray(msg.layout.dim.data)); + // First element + assert(typeof msg.layout.dim.data[0] === 'object'); + assert(msg.layout.dim.data[0].label === v.layout.dim[0].label); + assert(msg.layout.dim.data[0].size === v.layout.dim[0].size); + assert(msg.layout.dim.data[0].stride === v.layout.dim[0].stride); - // Second element - assert(typeof msg.layout.dim.data[1] === 'object'); - assert(msg.layout.dim.data[1].label === v.layout.dim[1].label); - assert(msg.layout.dim.data[1].size === v.layout.dim[1].size); - assert(msg.layout.dim.data[1].stride === v.layout.dim[1].stride); + // Second element + assert(typeof msg.layout.dim.data[1] === 'object'); + assert(msg.layout.dim.data[1].label === v.layout.dim[1].label); + assert(msg.layout.dim.data[1].size === v.layout.dim[1].size); + assert(msg.layout.dim.data[1].stride === v.layout.dim[1].stride); - assert(msg.layout.data_offset === v.layout.data_offset); + assert(msg.layout.data_offset === v.layout.data_offset); - assert(msg.data); - if (isTypedArray(v.data)) { - assert.deepStrictEqual(msg.data, v.data); - } else { - assert.ok(deepEqual(msg.data, v.data)); + assert(msg.data); + if (isTypedArray(v.data)) { + assert.deepStrictEqual(msg.data, v.data); + } else { + assert.ok(deepEqual(msg.data, v.data)); + } } - } - checkMessage(msg1); - checkMessage(msg2); + checkMessage(msg1); + checkMessage(msg2); - const o = v.data[0]; - assert(msg1.data[0] == o); - assert(msg2.data[0] == o); + const o = v.data[0]; + assert(msg1.data[0] == o); + assert(msg2.data[0] == o); - const r = Math.round(Math.random() * 100); - msg1.data[0] = r; + const r = Math.round(Math.random() * 100); + msg1.data[0] = r; - assert(msg1.data[0] == r); - assert(msg2.data[0] == o); + assert(msg1.data[0] == r); + assert(msg2.data[0] == o); + }); }); }); - }); + } const uint8Data = arrayGen.generateValues( Array, @@ -225,391 +248,396 @@ describe('rclnodejs message communication', function () { arrayGen.noRound ); - [ - /* eslint-disable camelcase */ - /* eslint-disable key-spacing */ - /* eslint-disable comma-spacing */ - { - pkg: 'sensor_msgs', - type: 'PointCloud2', - arrayType: Uint8Array, - property: 'data', - values: [ - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - height: 240, - width: 320, - fields: [], - is_bigendian: false, - point_step: 16, - row_step: 320 * 16, - data: uint8Data, - is_dense: false, - }, - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - height: 240, - width: 320, - fields: [], - is_bigendian: false, - point_step: 16, - row_step: 320 * 16, - data: Uint8Array.from(uint8Data), - is_dense: false, - }, - ], - }, - { - pkg: 'sensor_msgs', - type: 'Image', - arrayType: Uint8Array, - property: 'data', - values: [ - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - height: 240, - width: 320, - encoding: 'rgba', - is_bigendian: false, - step: 320 * 16, - is_dense: false, - data: uint8Data, - }, - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - height: 240, - width: 320, - encoding: 'rgba', - is_bigendian: false, - step: 320 * 16, - is_dense: false, - data: Uint8Array.from(uint8Data), - }, - ], - }, - { - pkg: 'sensor_msgs', - type: 'CompressedImage', - arrayType: Uint8Array, - property: 'data', - values: [ - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - format: 'jpeg', - data: uint8Data, - }, - { - header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, - format: 'jpeg', - data: Uint8Array.from(uint8Data), - }, - ], - }, - { - pkg: 'sensor_msgs', - type: 'ChannelFloat32', - arrayType: Float32Array, - property: 'values', - values: [ - { name: 'intensity', values: float32Data }, - { name: 'intensity', values: Float32Array.from(float32Data) }, - { - name: 'intensity', - values: Float32Array.from(Float32Array.from(float32Data)), - }, - ], - }, - { - pkg: 'sensor_msgs', - type: 'JointState', - arrayType: Float64Array, - property: 'position', - values: [ - { - header: { - stamp: { sec: 123456, nanosec: 789 }, - frame_id: 'main frame', + // similar to the above test, this requires introspection into the message by using the + // .hasMember method. The new bindings only support typed arrays so these tests are not + // really needed. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + [ + /* eslint-disable camelcase */ + /* eslint-disable key-spacing */ + /* eslint-disable comma-spacing */ + { + pkg: 'sensor_msgs', + type: 'PointCloud2', + arrayType: Uint8Array, + property: 'data', + values: [ + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + height: 240, + width: 320, + fields: [], + is_bigendian: false, + point_step: 16, + row_step: 320 * 16, + data: uint8Data, + is_dense: false, }, - name: ['Tom', 'Jerry'], - velocity: [2, 3], - effort: [4, 5, 6], - position: float64Data, - }, - { - header: { - stamp: { sec: 123456, nanosec: 789 }, - frame_id: 'main frame', + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + height: 240, + width: 320, + fields: [], + is_bigendian: false, + point_step: 16, + row_step: 320 * 16, + data: Uint8Array.from(uint8Data), + is_dense: false, }, - name: ['Tom', 'Jerry'], - velocity: [2, 3], - effort: [4, 5, 6], - position: Float64Array.from(float64Data), - }, - { - header: { - stamp: { sec: 123456, nanosec: 789 }, - frame_id: 'main frame', + ], + }, + { + pkg: 'sensor_msgs', + type: 'Image', + arrayType: Uint8Array, + property: 'data', + values: [ + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + height: 240, + width: 320, + encoding: 'rgba', + is_bigendian: false, + step: 320 * 16, + is_dense: false, + data: uint8Data, }, - name: ['Tom', 'Jerry'], - velocity: [2, 3], - effort: [4, 5, 6], - position: Float64Array.from(Float64Array.from(float64Data)), - }, - ], - }, - /* eslint-enable camelcase */ - /* eslint-enable key-spacing */ - /* eslint-enable comma-spacing */ - ].forEach((testData) => { - const topic = testData.topic || 'topic' + testData.type; - testData.values.forEach((v, i) => { - it( - 'Make sure ' + testData.type + ' use TypedArray' + ', case ' + i, - function () { - const MessageType = rclnodejs.require( - testData.pkg + '/msg/' + testData.type - ); - const msg = translator.toROSMessage(MessageType, v); - assert(isTypedArray(msg[testData.property])); - assert(msg[testData.property] instanceof testData.arrayType); + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + height: 240, + width: 320, + encoding: 'rgba', + is_bigendian: false, + step: 320 * 16, + is_dense: false, + data: Uint8Array.from(uint8Data), + }, + ], + }, + { + pkg: 'sensor_msgs', + type: 'CompressedImage', + arrayType: Uint8Array, + property: 'data', + values: [ + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + format: 'jpeg', + data: uint8Data, + }, + { + header: { stamp: { sec: 11223, nanosec: 44556 }, frame_id: 'f001' }, + format: 'jpeg', + data: Uint8Array.from(uint8Data), + }, + ], + }, + { + pkg: 'sensor_msgs', + type: 'ChannelFloat32', + arrayType: Float32Array, + property: 'values', + values: [ + { name: 'intensity', values: float32Data }, + { name: 'intensity', values: Float32Array.from(float32Data) }, + { + name: 'intensity', + values: Float32Array.from(Float32Array.from(float32Data)), + }, + ], + }, + { + pkg: 'sensor_msgs', + type: 'JointState', + arrayType: Float64Array, + property: 'position', + values: [ + { + header: { + stamp: { sec: 123456, nanosec: 789 }, + frame_id: 'main frame', + }, + name: ['Tom', 'Jerry'], + velocity: [2, 3], + effort: [4, 5, 6], + position: float64Data, + }, + { + header: { + stamp: { sec: 123456, nanosec: 789 }, + frame_id: 'main frame', + }, + name: ['Tom', 'Jerry'], + velocity: [2, 3], + effort: [4, 5, 6], + position: Float64Array.from(float64Data), + }, + { + header: { + stamp: { sec: 123456, nanosec: 789 }, + frame_id: 'main frame', + }, + name: ['Tom', 'Jerry'], + velocity: [2, 3], + effort: [4, 5, 6], + position: Float64Array.from(Float64Array.from(float64Data)), + }, + ], + }, + /* eslint-enable camelcase */ + /* eslint-enable key-spacing */ + /* eslint-enable comma-spacing */ + ].forEach((testData) => { + const topic = testData.topic || 'topic' + testData.type; + testData.values.forEach((v, i) => { + it( + 'Make sure ' + testData.type + ' use TypedArray' + ', case ' + i, + function () { + const MessageType = rclnodejs.require( + testData.pkg + '/msg/' + testData.type + ); + const msg = translator.toROSMessage(MessageType, v); + assert(isTypedArray(msg[testData.property])); + assert(msg[testData.property] instanceof testData.arrayType); - msg[testData.property] = v[testData.property]; - assert(isTypedArray(msg[testData.property])); - assert(msg[testData.property] instanceof testData.arrayType); + msg[testData.property] = v[testData.property]; + assert(isTypedArray(msg[testData.property])); + assert(msg[testData.property] instanceof testData.arrayType); - const msg2 = new MessageType(); - assert(isTypedArray(msg2[testData.property])); - assert(msg2[testData.property] instanceof testData.arrayType); - } - ); + const msg2 = new MessageType(); + assert(isTypedArray(msg2[testData.property])); + assert(msg2[testData.property] instanceof testData.arrayType); + } + ); + }); }); - }); - const arrayLength = 1024; - [ - /* eslint-disable max-len */ - { - type: 'ByteMultiArray', - arrayType: Uint8Array, - values: arrayGen.generateValues( - Uint8Array, - arrayLength, - 256, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'Float32MultiArray', - arrayType: Float32Array, - values: arrayGen.generateValues( - Float32Array, - arrayLength, - 10000, - arrayGen.negative, - arrayGen.noRound - ), - }, - { - type: 'Float64MultiArray', - arrayType: Float64Array, - values: arrayGen.generateValues( - Float64Array, - arrayLength, - 10000, - arrayGen.negative, - arrayGen.noRound - ), - }, - { - type: 'Int8MultiArray', - arrayType: Int8Array, - values: arrayGen.generateValues( - Int8Array, - arrayLength, - 128, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'Int16MultiArray', - arrayType: Int16Array, - values: arrayGen.generateValues( - Int16Array, - arrayLength, - 32768, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'Int32MultiArray', - arrayType: Int32Array, - values: arrayGen.generateValues( - Int32Array, - arrayLength, - 2147483648, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'UInt8MultiArray', - arrayType: Uint8Array, - values: arrayGen.generateValues( - Uint8Array, - arrayLength, - 256, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'UInt16MultiArray', - arrayType: Uint16Array, - values: arrayGen.generateValues( - Uint16Array, - arrayLength, - 65536, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'UInt32MultiArray', - arrayType: Uint32Array, - values: arrayGen.generateValues( - Uint32Array, - arrayLength, - 4294967296, - arrayGen.positive, - Math.floor - ), - }, + const arrayLength = 1024; + [ + /* eslint-disable max-len */ + { + type: 'ByteMultiArray', + arrayType: Uint8Array, + values: arrayGen.generateValues( + Uint8Array, + arrayLength, + 256, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'Float32MultiArray', + arrayType: Float32Array, + values: arrayGen.generateValues( + Float32Array, + arrayLength, + 10000, + arrayGen.negative, + arrayGen.noRound + ), + }, + { + type: 'Float64MultiArray', + arrayType: Float64Array, + values: arrayGen.generateValues( + Float64Array, + arrayLength, + 10000, + arrayGen.negative, + arrayGen.noRound + ), + }, + { + type: 'Int8MultiArray', + arrayType: Int8Array, + values: arrayGen.generateValues( + Int8Array, + arrayLength, + 128, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'Int16MultiArray', + arrayType: Int16Array, + values: arrayGen.generateValues( + Int16Array, + arrayLength, + 32768, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'Int32MultiArray', + arrayType: Int32Array, + values: arrayGen.generateValues( + Int32Array, + arrayLength, + 2147483648, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'UInt8MultiArray', + arrayType: Uint8Array, + values: arrayGen.generateValues( + Uint8Array, + arrayLength, + 256, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'UInt16MultiArray', + arrayType: Uint16Array, + values: arrayGen.generateValues( + Uint16Array, + arrayLength, + 65536, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'UInt32MultiArray', + arrayType: Uint32Array, + values: arrayGen.generateValues( + Uint32Array, + arrayLength, + 4294967296, + arrayGen.positive, + Math.floor + ), + }, - { - type: 'ByteMultiArray', - arrayType: Uint8Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 256, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'Float32MultiArray', - arrayType: Float32Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 10000, - arrayGen.negative, - arrayGen.noRound - ), - }, - { - type: 'Float64MultiArray', - arrayType: Float64Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 10000, - arrayGen.negative, - arrayGen.noRound - ), - }, - { - type: 'Int8MultiArray', - arrayType: Int8Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 128, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'Int16MultiArray', - arrayType: Int16Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 32768, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'Int32MultiArray', - arrayType: Int32Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 2147483648, - arrayGen.negative, - Math.floor - ), - }, - { - type: 'UInt8MultiArray', - arrayType: Uint8Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 256, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'UInt16MultiArray', - arrayType: Uint16Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 65536, - arrayGen.positive, - Math.floor - ), - }, - { - type: 'UInt32MultiArray', - arrayType: Uint32Array, - values: arrayGen.generateValues( - Array, - arrayLength, - 4294967296, - arrayGen.positive, - Math.floor - ), - }, - /* eslint-enable max-len */ - ].forEach((testData) => { - const topic = testData.topic || 'topic' + testData.type; - it('Make sure ' + testData.type + ' use TypedArray', function () { - const MessageType = rclnodejs.require('std_msgs/msg/' + testData.type); - const msg = translator.toROSMessage(MessageType, { - layout: { - dim: [{ label: 'length', size: 0, stride: 0 }], - // eslint-disable-next-line - data_offset: 0, - }, - data: testData.values, - }); - assert(isTypedArray(msg.data)); - assert(msg.data instanceof testData.arrayType); + { + type: 'ByteMultiArray', + arrayType: Uint8Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 256, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'Float32MultiArray', + arrayType: Float32Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 10000, + arrayGen.negative, + arrayGen.noRound + ), + }, + { + type: 'Float64MultiArray', + arrayType: Float64Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 10000, + arrayGen.negative, + arrayGen.noRound + ), + }, + { + type: 'Int8MultiArray', + arrayType: Int8Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 128, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'Int16MultiArray', + arrayType: Int16Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 32768, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'Int32MultiArray', + arrayType: Int32Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 2147483648, + arrayGen.negative, + Math.floor + ), + }, + { + type: 'UInt8MultiArray', + arrayType: Uint8Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 256, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'UInt16MultiArray', + arrayType: Uint16Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 65536, + arrayGen.positive, + Math.floor + ), + }, + { + type: 'UInt32MultiArray', + arrayType: Uint32Array, + values: arrayGen.generateValues( + Array, + arrayLength, + 4294967296, + arrayGen.positive, + Math.floor + ), + }, + /* eslint-enable max-len */ + ].forEach((testData) => { + const topic = testData.topic || 'topic' + testData.type; + it('Make sure ' + testData.type + ' use TypedArray', function () { + const MessageType = rclnodejs.require('std_msgs/msg/' + testData.type); + const msg = translator.toROSMessage(MessageType, { + layout: { + dim: [{ label: 'length', size: 0, stride: 0 }], + // eslint-disable-next-line + data_offset: 0, + }, + data: testData.values, + }); + assert(isTypedArray(msg.data)); + assert(msg.data instanceof testData.arrayType); - msg.data = testData.values; - assert(isTypedArray(msg.data)); - assert(msg.data instanceof testData.arrayType); + msg.data = testData.values; + assert(isTypedArray(msg.data)); + assert(msg.data instanceof testData.arrayType); - const msg2 = new MessageType(); - assert(isTypedArray(msg2.data)); - assert(msg2.data instanceof testData.arrayType); + const msg2 = new MessageType(); + assert(isTypedArray(msg2.data)); + assert(msg2.data instanceof testData.arrayType); + }); }); - }); + } }); diff --git a/test/test-compound-msg-type-check.js b/test/test-compound-msg-type-check.js index 721408dc..5db72ab1 100644 --- a/test/test-compound-msg-type-check.js +++ b/test/test-compound-msg-type-check.js @@ -40,17 +40,20 @@ describe('Compound types', function () { assert.deepStrictEqual(typeof msg.a, 'undefined'); }); - it('Array', function () { - const Byte = rclnodejs.require('std_msgs').msg.Byte; - const ByteArray = Byte.ArrayType; - let msg = new ByteArray(3); - msg.fill([1, 2, 3]); + // there is no special array wrappers in the new bindings + if (!process.env.RCLNODEJS_USE_ROSIDL) { + it('Array', function () { + const Byte = rclnodejs.require('std_msgs').msg.Byte; + const ByteArray = Byte.ArrayType; + let msg = new ByteArray(3); + msg.fill([1, 2, 3]); - assert.deepStrictEqual(msg.data.length, 3); - assert.deepStrictEqual(msg.data[0], 1); - assert.deepStrictEqual(msg.data[1], 2); - assert.deepStrictEqual(msg.data[2], 3); - }); + assert.deepStrictEqual(msg.data.length, 3); + assert.deepStrictEqual(msg.data[0], 1); + assert.deepStrictEqual(msg.data[1], 2); + assert.deepStrictEqual(msg.data[2], 3); + }); + } it('Object with Header', function () { const Header = rclnodejs.require('std_msgs').msg.Header; @@ -59,7 +62,12 @@ describe('Compound types', function () { assert.ok('stamp' in header); assert.ok('frame_id' in header); - assert.deepStrictEqual(typeof header.stamp, 'object'); + // the new bindings doesn't populate fields on creation + if (process.env.RCLNODEJS_USE_ROSIDL) { + assert.deepStrictEqual(typeof header.stamp, 'undefined'); + } else { + assert.deepStrictEqual(typeof header.stamp, 'object'); + } assert.deepStrictEqual(typeof header.frame_id, 'undefined'); }); diff --git a/test/test-disable-typedarray.js b/test/test-disable-typedarray.js index 6ac3deae..edb03946 100644 --- a/test/test-disable-typedarray.js +++ b/test/test-disable-typedarray.js @@ -21,7 +21,7 @@ const rclnodejs = require('../index.js'); /* eslint-disable key-spacing */ /* eslint-disable comma-spacing */ // rosidl generator only supports typed array -if (process.env.RCLNODEJS_USE_ROSIDL) { +if (!process.env.RCLNODEJS_USE_ROSIDL) { describe('rclnodejs message communication', function () { this.timeout(60 * 1000); From 3a807b7408c2a83d0381f2697a9ef2a083dc7d26 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 12:43:43 +0800 Subject: [PATCH 48/64] generate messages for actions --- rosidl_gen/idl_generator.js | 124 ++++++++++++++++++++++--- rosidl_gen/templates/messageRosidl.dot | 11 +++ test/test-message-object.js | 22 ++++- 3 files changed, 142 insertions(+), 15 deletions(-) diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index ae315329..9477c95c 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -201,10 +201,10 @@ function pascalToSnakeCase(s) { } function getRosHeaderField(messageInfo) { - if (isServiceMessage(messageInfo)) { + if (isInternalMessage(messageInfo)) { const interfaceName = messageInfo.interfaceName.slice( 0, - messageInfo.interfaceName.lastIndexOf('_') + messageInfo.interfaceName.indexOf('_') ); return `${messageInfo.pkgName}/${messageInfo.subFolder}/${pascalToSnakeCase( interfaceName @@ -313,11 +313,8 @@ function isInternalField(field) { return field.name.startsWith('_'); } -function isServiceMessage(messageInfo) { - return ( - messageInfo.interfaceName.endsWith('_Request') || - messageInfo.interfaceName.endsWith('_Response') - ); +function isInternalMessage(messageInfo) { + return messageInfo.interfaceName.indexOf('_') !== -1; } // All messages are combined in one cpp file to improve compile time. @@ -335,13 +332,29 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { return getStructType(messageInfo); }; - const messages = await Promise.all( - pkgInfo.messages.map(async (messageInfo) => ({ + const messages = await Promise.all([ + ...pkgInfo.messages.map(async (messageInfo) => ({ info: messageInfo, spec: await rosIdlDb.getMessageSpec(messageInfo), structType: getStructType(messageInfo), - })) - ); + })), + ...( + await Promise.all( + pkgInfo.actions.map(async (actionInfo) => { + const msgInfosAndSpecs = await getActionMessageInfosAndSpecs( + actionInfo + ); + return Object.values(msgInfosAndSpecs).map( + async ({ info, spec }) => ({ + info: info, + spec: spec, + structType: getStructType(info), + }) + ); + }) + ) + ).flat(), + ]); const includeHeadersSet = new Set(); messages.forEach(({ info }) => { @@ -386,6 +399,95 @@ async function generateCppDefinitions(pkgName, pkgInfo, rosIdlDb, options) { await fs.writeFile(path.join(outputDir, 'definitions.hpp'), header); } +async function getActionMessageInfosAndSpecs(actionInfo) { + const spec = await parser.parseActionFile( + actionInfo.pkgName, + actionInfo.filePath + ); + + return { + goal: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_Goal`, + }, + spec: spec.goal, + }, + result: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_Result`, + }, + spec: spec.result, + }, + feedback: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_Feedback`, + }, + spec: spec.feedback, + }, + sendGoalRequest: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_SendGoal_Request`, + }, + spec: actionMsgs.createSendGoalRequestSpec( + actionInfo.pkgName, + actionInfo.interfaceName + ), + }, + sendGoalResponse: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_SendGoal_Response`, + }, + spec: actionMsgs.createSendGoalResponseSpec( + actionInfo.pkgName, + actionInfo.interfaceName + ), + }, + getResultRequest: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_GetResult_Request`, + }, + spec: actionMsgs.createGetResultRequestSpec( + actionInfo.pkgName, + actionInfo.interfaceName + ), + }, + getResultResponse: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_GetResult_Response`, + }, + spec: actionMsgs.createGetResultResponseSpec( + actionInfo.pkgName, + actionInfo.interfaceName + ), + }, + feedbackMessage: { + info: { + pkgName: actionInfo.pkgName, + subFolder: actionInfo.subFolder, + interfaceName: `${actionInfo.interfaceName}_FeedbackMessage`, + }, + spec: actionMsgs.createFeedbackMessageSpec( + actionInfo.pkgName, + actionInfo.interfaceName + ), + }, + }; +} + async function generateActionJSStruct(actionInfo, dir, options) { const spec = await parser.parseActionFile( actionInfo.pkgName, diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index 18cc65fe..c5eea10a 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -251,6 +251,17 @@ class {{=objectWrapper}} { } } +{{? it.spec.constants != undefined && it.spec.constants.length}} +// Define constants ({{=it.spec.constants.length}} in total) +{{~ it.spec.constants :c}} +{{? c.type === "string"}} +Object.defineProperty({{=objectWrapper}}, "{{=c.name}}", {value: "{{=c.value}}", writable: false, enumerable: true, configurable: true}); +{{?? true}} +Object.defineProperty({{=objectWrapper}}, "{{=c.name}}", {value: {{=c.value}}, writable: false, enumerable: true, configurable: true}); +{{?}} +{{~}} +{{?}} + module.exports = {{=objectWrapper}}; /* diff --git a/test/test-message-object.js b/test/test-message-object.js index b0efc449..1a762b58 100644 --- a/test/test-message-object.js +++ b/test/test-message-object.js @@ -38,6 +38,10 @@ describe('Rclnodejs createMessage() testing', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { + if (process.env.RCLNODEJS_USE_ROSIDL) { + // this packages contains invalid messages + pkgs.delete('libstatistics_collector'); + } pkgs.forEach((pkg) => { pkg.messages.forEach((info) => { const s = @@ -179,6 +183,10 @@ describe('Rclnodejs createMessageObject() testing', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { + if (process.env.RCLNODEJS_USE_ROSIDL) { + // this packages contains invalid messages + pkgs.delete('libstatistics_collector'); + } pkgs.forEach((pkg) => { pkg.messages.forEach((info) => { const s = @@ -201,8 +209,11 @@ describe('Rclnodejs createMessageObject() testing', function () { it('create by string', function () { const s = rclnodejs.createMessageObject('std_msgs/msg/String'); - assert('data' in s); - assert(!s.data); + // fields are not prepopulated in the new bindings + if (!process.env.RCLNODEJS_USE_ROSIDL) { + assert('data' in s); + assert(!s.data); + } s.data = 'this is fun'; assert.equal(typeof s.data, 'string'); assert.equal(s.data, 'this is fun'); @@ -215,8 +226,11 @@ describe('Rclnodejs createMessageObject() testing', function () { name: 'String', }); - assert('data' in s); - assert(!s.data); + // fields are not prepopulated in the new bindings + if (!process.env.RCLNODEJS_USE_ROSIDL) { + assert('data' in s); + assert(!s.data); + } s.data = 'this is fun'; assert.equal(typeof s.data, 'string'); assert.equal(s.data, 'this is fun'); From 046911639f522c50f8d4940633807b2da1586c8a Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 13:04:38 +0800 Subject: [PATCH 49/64] revert change to skip zero initialization --- rosidl_gen/templates/messageRosidl.dot | 2 +- test/test-array-data.js | 8 ++---- test/test-compound-msg-type-check.js | 8 +++--- test/test-message-object.js | 14 +++------- test/test-non-primitive-msg-type-check.js | 33 ++++++++++++++--------- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index c5eea10a..cccc5fd4 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -148,7 +148,7 @@ class {{=objectWrapper}} { this._rawRos = undefined; if (other === undefined) { this._rawRos = {{=objectWrapper}}._createRosMessage(); - this._proxyObj = {}; + this._proxyObj = {{=objectWrapper}}._toJsObject(this._rawRos); } else if (other instanceof {{=objectWrapper}}) { this._proxyObj = other._proxyObj; } else { diff --git a/test/test-array-data.js b/test/test-array-data.js index df481d87..20a7c55b 100644 --- a/test/test-array-data.js +++ b/test/test-array-data.js @@ -48,12 +48,8 @@ describe('rclnodejs message communication', function () { data_offset: 0, }; - // Unlike the old bindings, the new rosidl bindings does not use a message translator. - // Messages are just plain js objects until serialization, a side effect is that there - // is no "zero initialization" at message creation time. It causes this test to fail - // because it depends on being able to introspect the message by recursively calling - // each fields .hasMember function. This test is also not really needed as there is no - // logic in the .copy method in the new bindings. + // The new bindings initialize nested message as plain js objects instead of the wrappers. + // As a result, they don't contain .hasMember methods that this test needs. if (!process.env.RCLNODEJS_USE_ROSIDL) { [ { diff --git a/test/test-compound-msg-type-check.js b/test/test-compound-msg-type-check.js index 5db72ab1..4cb0fd40 100644 --- a/test/test-compound-msg-type-check.js +++ b/test/test-compound-msg-type-check.js @@ -62,13 +62,13 @@ describe('Compound types', function () { assert.ok('stamp' in header); assert.ok('frame_id' in header); - // the new bindings doesn't populate fields on creation + assert.deepStrictEqual(typeof header.stamp, 'object'); + // the new bindings correctly initialize strings as an empty string instead of undefined. if (process.env.RCLNODEJS_USE_ROSIDL) { - assert.deepStrictEqual(typeof header.stamp, 'undefined'); + assert.deepStrictEqual(typeof header.frame_id, 'string'); } else { - assert.deepStrictEqual(typeof header.stamp, 'object'); + assert.deepStrictEqual(typeof header.frame_id, 'undefined'); } - assert.deepStrictEqual(typeof header.frame_id, 'undefined'); }); it('Complex object', function () { diff --git a/test/test-message-object.js b/test/test-message-object.js index 1a762b58..d946d2c3 100644 --- a/test/test-message-object.js +++ b/test/test-message-object.js @@ -209,11 +209,8 @@ describe('Rclnodejs createMessageObject() testing', function () { it('create by string', function () { const s = rclnodejs.createMessageObject('std_msgs/msg/String'); - // fields are not prepopulated in the new bindings - if (!process.env.RCLNODEJS_USE_ROSIDL) { - assert('data' in s); - assert(!s.data); - } + assert('data' in s); + assert(!s.data); s.data = 'this is fun'; assert.equal(typeof s.data, 'string'); assert.equal(s.data, 'this is fun'); @@ -226,11 +223,8 @@ describe('Rclnodejs createMessageObject() testing', function () { name: 'String', }); - // fields are not prepopulated in the new bindings - if (!process.env.RCLNODEJS_USE_ROSIDL) { - assert('data' in s); - assert(!s.data); - } + assert('data' in s); + assert(!s.data); s.data = 'this is fun'; assert.equal(typeof s.data, 'string'); assert.equal(s.data, 'this is fun'); diff --git a/test/test-non-primitive-msg-type-check.js b/test/test-non-primitive-msg-type-check.js index f459b214..1136545b 100644 --- a/test/test-non-primitive-msg-type-check.js +++ b/test/test-non-primitive-msg-type-check.js @@ -60,18 +60,27 @@ describe('Rclnodejs non primitive message type testing', function () { assert.deepStrictEqual(44556, jointStateClone.header.stamp.nanosec); assert.deepStrictEqual('1234567x', jointStateClone.header.frame_id); assert.deepStrictEqual(['Willy', 'Tacky'], jointStateClone.name); - assert.deepStrictEqual( - Float64Array.from([1, 7, 3, 4, 2, 2, 8]), - jointStateClone.position - ); - assert.deepStrictEqual( - Float64Array.from([8, 9, 6, 4]), - jointStateClone.velocity - ); - assert.deepStrictEqual( - Float64Array.from([1, 0, 2, 6, 7]), - jointStateClone.effort - ); + + // new bindings does not do conversion until serialization so it doesn't automatically + // converts number arrays to typed arrays on assignment. + if (process.env.RCLNODEJS_USE_ROSIDL) { + assert.deepStrictEqual([1, 7, 3, 4, 2, 2, 8], jointStateClone.position); + assert.deepStrictEqual([8, 9, 6, 4], jointStateClone.velocity); + assert.deepStrictEqual([1, 0, 2, 6, 7], jointStateClone.effort); + } else { + assert.deepStrictEqual( + Float64Array.from([1, 7, 3, 4, 2, 2, 8]), + jointStateClone.position + ); + assert.deepStrictEqual( + Float64Array.from([8, 9, 6, 4]), + jointStateClone.velocity + ); + assert.deepStrictEqual( + Float64Array.from([1, 0, 2, 6, 7]), + jointStateClone.effort + ); + } }); it('geometry_msgs/msg/Transform checking', function () { From 123a0fad5b16af785ec1b1f03b9d9b8125af0d2b Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 13:13:56 +0800 Subject: [PATCH 50/64] pass non-primitive-msg-type test --- test/test-non-primitive-msg-type-check.js | 139 ++++++++++++---------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/test/test-non-primitive-msg-type-check.js b/test/test-non-primitive-msg-type-check.js index 1136545b..1688891a 100644 --- a/test/test-non-primitive-msg-type-check.js +++ b/test/test-non-primitive-msg-type-check.js @@ -105,67 +105,80 @@ describe('Rclnodejs non primitive message type testing', function () { assert.deepStrictEqual(1.0, transformClone.rotation.w); }); - it('std_msgs/msg/Float32MultiArray checking', function () { - const Float32MultiArray = rclnodejs.require( - 'std_msgs/msg/Float32MultiArray' - ); - const MultiArrayDimension = rclnodejs.require( - 'std_msgs/msg/MultiArrayDimension' - ); - - let float32MultiArray = new Float32MultiArray(); - let heightDimension = new MultiArrayDimension(); - heightDimension.label = 'height'; - heightDimension.size = 480; - heightDimension.stride = 921600; - - let weightDimension = new MultiArrayDimension(); - weightDimension.label = 'weight'; - weightDimension.size = 640; - weightDimension.stride = 1920; - - let channelDimension = new MultiArrayDimension(); - channelDimension.label = 'channel'; - channelDimension.size = 3; - channelDimension.stride = 8; - - float32MultiArray.layout.dim.fill([ - heightDimension, - weightDimension, - channelDimension, - ]); - float32MultiArray.layout.data_offset = 1024; - float32MultiArray.data = [1.0, 2.0, 3.0, 8.5, 6.75, 0.5, -0.25]; - - let float32MultiArrayClone = new Float32MultiArray(float32MultiArray); - assert.deepStrictEqual( - 'height', - float32MultiArrayClone.layout.dim.data[0].label - ); - assert.deepStrictEqual(480, float32MultiArrayClone.layout.dim.data[0].size); - assert.deepStrictEqual( - 921600, - float32MultiArrayClone.layout.dim.data[0].stride - ); - assert.deepStrictEqual( - 'weight', - float32MultiArrayClone.layout.dim.data[1].label - ); - assert.deepStrictEqual(640, float32MultiArrayClone.layout.dim.data[1].size); - assert.deepStrictEqual( - 1920, - float32MultiArrayClone.layout.dim.data[1].stride - ); - assert.deepStrictEqual( - 'channel', - float32MultiArrayClone.layout.dim.data[2].label - ); - assert.deepStrictEqual(3, float32MultiArrayClone.layout.dim.data[2].size); - assert.deepStrictEqual(8, float32MultiArrayClone.layout.dim.data[2].stride); - assert.deepStrictEqual(1024, float32MultiArrayClone.layout.data_offset); - assert.deepStrictEqual( - Float32Array.from([1.0, 2.0, 3.0, 8.5, 6.75, 0.5, -0.25]), - float32MultiArrayClone.data - ); - }); + // not sure how this test works, `Float32MultiArray.layout.dim.data` is not a valid + // field, `MultiArrayDimensions` does not have a `data` field. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + it('std_msgs/msg/Float32MultiArray checking', function () { + const Float32MultiArray = rclnodejs.require( + 'std_msgs/msg/Float32MultiArray' + ); + const MultiArrayDimension = rclnodejs.require( + 'std_msgs/msg/MultiArrayDimension' + ); + + let float32MultiArray = new Float32MultiArray(); + let heightDimension = new MultiArrayDimension(); + heightDimension.label = 'height'; + heightDimension.size = 480; + heightDimension.stride = 921600; + + let weightDimension = new MultiArrayDimension(); + weightDimension.label = 'weight'; + weightDimension.size = 640; + weightDimension.stride = 1920; + + let channelDimension = new MultiArrayDimension(); + channelDimension.label = 'channel'; + channelDimension.size = 3; + channelDimension.stride = 8; + + float32MultiArray.layout.dim.fill([ + heightDimension, + weightDimension, + channelDimension, + ]); + float32MultiArray.layout.data_offset = 1024; + float32MultiArray.data = [1.0, 2.0, 3.0, 8.5, 6.75, 0.5, -0.25]; + + let float32MultiArrayClone = new Float32MultiArray(float32MultiArray); + assert.deepStrictEqual( + 'height', + float32MultiArrayClone.layout.dim.data[0].label + ); + assert.deepStrictEqual( + 480, + float32MultiArrayClone.layout.dim.data[0].size + ); + assert.deepStrictEqual( + 921600, + float32MultiArrayClone.layout.dim.data[0].stride + ); + assert.deepStrictEqual( + 'weight', + float32MultiArrayClone.layout.dim.data[1].label + ); + assert.deepStrictEqual( + 640, + float32MultiArrayClone.layout.dim.data[1].size + ); + assert.deepStrictEqual( + 1920, + float32MultiArrayClone.layout.dim.data[1].stride + ); + assert.deepStrictEqual( + 'channel', + float32MultiArrayClone.layout.dim.data[2].label + ); + assert.deepStrictEqual(3, float32MultiArrayClone.layout.dim.data[2].size); + assert.deepStrictEqual( + 8, + float32MultiArrayClone.layout.dim.data[2].stride + ); + assert.deepStrictEqual(1024, float32MultiArrayClone.layout.data_offset); + assert.deepStrictEqual( + Float32Array.from([1.0, 2.0, 3.0, 8.5, 6.75, 0.5, -0.25]), + float32MultiArrayClone.data + ); + }); + } }); From 3bd83bd764da09fe1c883dfa2610b61e8c518b87 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 13:17:25 +0800 Subject: [PATCH 51/64] skip type check tests --- test/test-primitive-msg-type-check.js | 638 +++++++++++++------------- 1 file changed, 321 insertions(+), 317 deletions(-) diff --git a/test/test-primitive-msg-type-check.js b/test/test-primitive-msg-type-check.js index ea112f24..d1ee4567 100644 --- a/test/test-primitive-msg-type-check.js +++ b/test/test-primitive-msg-type-check.js @@ -18,321 +18,325 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); const assertThrowsError = require('./utils.js').assertThrowsError; -describe('Rclnodejs message type data testing', function () { - this.timeout(60 * 1000); - - before(function () { - return rclnodejs.init(); - }); - - after(function () { - rclnodejs.shutdown(); - }); - - it('Bool data checking', function () { - var node = rclnodejs.createNode('bool'); - var msgBool = rclnodejs.require('std_msgs').msg.Bool; - var msg = new msgBool(); - - msg.data = true; - assert.ok(msg.data); - - msg.data = false; - assert.ok(!msg.data); - - msg.data = 1; - assert.ok(msg.data); - - msg.data = 0; - assert.ok(!msg.data); - - msg.data = 'ABc'; - assert.ok(msg.data); - - msg.data = ''; - assert.ok(!msg.data); - }); - - it('Char data checking', function () { - var node = rclnodejs.createNode('char'); - var msgChar = rclnodejs.require('std_msgs').msg.Char; - var msg = new msgChar(); - - msg.data = 'A'; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 65); - - assertThrowsError( - () => { - msg.data = -129; - }, - [TypeError, RangeError], - 'out of bounds', - 'Char should be in [-128, 127]' - ); - assertThrowsError( - () => { - msg.data = 128; - }, - [TypeError, RangeError], - 'out of bounds', - 'Char should be in [-128, 127]' - ); - }); - - it('Byte data checking', function () { - var node = rclnodejs.createNode('byte'); - var msgByte = rclnodejs.require('std_msgs').msg.Byte; - var msg = new msgByte(); - - msg.data = 0xa; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 10); - - assertThrowsError( - () => { - msg.data = -1; - }, - [TypeError, RangeError], - 'out of bounds', - 'Byte should be in [0, 255]' - ); - assertThrowsError( - () => { - msg.data = 256; - }, - [TypeError, RangeError], - 'out of bounds', - 'Byte should be in [0, 255]' - ); - }); - - it('String data checking', function () { - var node = rclnodejs.createNode('string'); - var msgString = rclnodejs.require('std_msgs').msg.String; - var msg = new msgString(); - - msg.data = 'rclnodejs'; - assert.deepStrictEqual(typeof msg.data, 'string'); - assert.deepStrictEqual(msg.data, 'rclnodejs'); - - assertThrowsError( - () => { - msg.data = 1; - }, - [TypeError, RangeError], - 'Number/String 64-bit value required', - 'String data is not a string' - ); - assertThrowsError( - () => { - msg.data = 3.14; - }, - [TypeError, RangeError], - 'Number/String 64-bit value required', - 'String data is not a string' - ); - }); - - it('Int8 data checking', function () { - var node = rclnodejs.createNode('int8'); - var msgInt8 = rclnodejs.require('std_msgs').msg.Int8; - var msg = new msgInt8(); - - msg.data = 0x7f; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 127); - - assertThrowsError( - () => { - msg.data = -129; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int8 should be in [-128, 127]' - ); - assertThrowsError( - () => { - msg.data = 128; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int8 should be in [-128, 127]' - ); - }); - - it('UInt8 data checking', function () { - var node = rclnodejs.createNode('uint8'); - var msgUInt8 = rclnodejs.require('std_msgs').msg.UInt8; - var msg = new msgUInt8(); - - msg.data = 0xff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 255); - - assertThrowsError( - () => { - msg.data = -1; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt8 should be in [0, 256]' - ); - assertThrowsError( - () => { - msg.data = 256; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt8 should be in [0, 256]' - ); - }); - - it('Int16 data checking', function () { - var node = rclnodejs.createNode('int16'); - var msgInt16 = rclnodejs.require('std_msgs').msg.Int16; - var msg = new msgInt16(); - - msg.data = 0x7fff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 0x7fff); - - assertThrowsError( - () => { - msg.data = -0x7fff - 2; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int16 should be in [-0x7fff, 0x7fff]' - ); - assertThrowsError( - () => { - msg.data = 0x7ffff + 1; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int16 should be in [-0x7fff, 0x7fff]' - ); - }); - - it('UInt16 data checking', function () { - var node = rclnodejs.createNode('uint16'); - var msgUInt16 = rclnodejs.require('std_msgs').msg.UInt16; - var msg = new msgUInt16(); - - msg.data = 0xffff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 0xffff); - - assertThrowsError( - () => { - msg.data = -1; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt16 should be in [0, 0xffff]' - ); - assertThrowsError( - () => { - msg.data = 0xffff + 1; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt16 should be in [0, 0xffff]' - ); - }); - - it('Int32 data checking', function () { - var node = rclnodejs.createNode('int32'); - var msgInt32 = rclnodejs.require('std_msgs').msg.Int32; - var msg = new msgInt32(); - - msg.data = 0x7fffffff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 0x7fffffff); - - assertThrowsError( - () => { - msg.data = -0x7fffffff - 2; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int32 should be in [-0x7fffffff - 1, 0x7fffffff]' - ); - assertThrowsError( - () => { - msg.data = 0x7ffffffff + 1; - }, - [TypeError, RangeError], - 'out of bounds', - 'Int32 should be in [-0x7fffffff - 1, 0x7fffffff]' - ); - }); - - it('UInt32 data checking', function () { - var node = rclnodejs.createNode('uint32'); - var msgUInt32 = rclnodejs.require('std_msgs').msg.UInt32; - var msg = new msgUInt32(); - - msg.data = 0xffffffff; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.deepStrictEqual(msg.data, 0xffffffff); - - assertThrowsError( - () => { - msg.data = -1; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt32 should be in [0, 0xffffffff]' - ); - assertThrowsError( - () => { - msg.data = 0xffffffff + 1; - }, - [TypeError, RangeError], - 'out of bounds', - 'UInt32 should be in [0, 0xffffffff]' - ); - }); - - it('Int64 data checking', function () { - var node = rclnodejs.createNode('int64'); - 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); - }); - - it('UInt64 data checking', function () { - var node = rclnodejs.createNode('uint64'); - 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); - }); - - it('Float32 data checking', function () { - var node = rclnodejs.createNode('float32'); - var msgFloat32 = rclnodejs.require('std_msgs').msg.Float32; - var msg = new msgFloat32(); - - msg.data = 3.14; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.ok(Math.abs(msg.data - 3.14) < 0.000001); - }); - - it('Float64 data checking', function () { - var node = rclnodejs.createNode('float64'); - var msgFloat64 = rclnodejs.require('std_msgs').msg.Float64; - var msg = new msgFloat64(); - - msg.data = 3.14; - assert.deepStrictEqual(typeof msg.data, 'number'); - assert.ok(Math.abs(msg.data - 3.14) < 0.000001); +// new bindings does not do type checking, invalid types are automatically +// converted to the "zero" value. +if (!process.env.RCLNODEJS_USE_ROSIDL) { + describe('Rclnodejs message type data testing', function () { + this.timeout(60 * 1000); + + before(function () { + return rclnodejs.init(); + }); + + after(function () { + rclnodejs.shutdown(); + }); + + it('Bool data checking', function () { + var node = rclnodejs.createNode('bool'); + var msgBool = rclnodejs.require('std_msgs').msg.Bool; + var msg = new msgBool(); + + msg.data = true; + assert.ok(msg.data); + + msg.data = false; + assert.ok(!msg.data); + + msg.data = 1; + assert.ok(msg.data); + + msg.data = 0; + assert.ok(!msg.data); + + msg.data = 'ABc'; + assert.ok(msg.data); + + msg.data = ''; + assert.ok(!msg.data); + }); + + it('Char data checking', function () { + var node = rclnodejs.createNode('char'); + var msgChar = rclnodejs.require('std_msgs').msg.Char; + var msg = new msgChar(); + + msg.data = 'A'; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 65); + + assertThrowsError( + () => { + msg.data = -129; + }, + [TypeError, RangeError], + 'out of bounds', + 'Char should be in [-128, 127]' + ); + assertThrowsError( + () => { + msg.data = 128; + }, + [TypeError, RangeError], + 'out of bounds', + 'Char should be in [-128, 127]' + ); + }); + + it('Byte data checking', function () { + var node = rclnodejs.createNode('byte'); + var msgByte = rclnodejs.require('std_msgs').msg.Byte; + var msg = new msgByte(); + + msg.data = 0xa; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 10); + + assertThrowsError( + () => { + msg.data = -1; + }, + [TypeError, RangeError], + 'out of bounds', + 'Byte should be in [0, 255]' + ); + assertThrowsError( + () => { + msg.data = 256; + }, + [TypeError, RangeError], + 'out of bounds', + 'Byte should be in [0, 255]' + ); + }); + + it('String data checking', function () { + var node = rclnodejs.createNode('string'); + var msgString = rclnodejs.require('std_msgs').msg.String; + var msg = new msgString(); + + msg.data = 'rclnodejs'; + assert.deepStrictEqual(typeof msg.data, 'string'); + assert.deepStrictEqual(msg.data, 'rclnodejs'); + + assertThrowsError( + () => { + msg.data = 1; + }, + [TypeError, RangeError], + 'Number/String 64-bit value required', + 'String data is not a string' + ); + assertThrowsError( + () => { + msg.data = 3.14; + }, + [TypeError, RangeError], + 'Number/String 64-bit value required', + 'String data is not a string' + ); + }); + + it('Int8 data checking', function () { + var node = rclnodejs.createNode('int8'); + var msgInt8 = rclnodejs.require('std_msgs').msg.Int8; + var msg = new msgInt8(); + + msg.data = 0x7f; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 127); + + assertThrowsError( + () => { + msg.data = -129; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int8 should be in [-128, 127]' + ); + assertThrowsError( + () => { + msg.data = 128; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int8 should be in [-128, 127]' + ); + }); + + it('UInt8 data checking', function () { + var node = rclnodejs.createNode('uint8'); + var msgUInt8 = rclnodejs.require('std_msgs').msg.UInt8; + var msg = new msgUInt8(); + + msg.data = 0xff; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 255); + + assertThrowsError( + () => { + msg.data = -1; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt8 should be in [0, 256]' + ); + assertThrowsError( + () => { + msg.data = 256; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt8 should be in [0, 256]' + ); + }); + + it('Int16 data checking', function () { + var node = rclnodejs.createNode('int16'); + var msgInt16 = rclnodejs.require('std_msgs').msg.Int16; + var msg = new msgInt16(); + + msg.data = 0x7fff; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 0x7fff); + + assertThrowsError( + () => { + msg.data = -0x7fff - 2; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int16 should be in [-0x7fff, 0x7fff]' + ); + assertThrowsError( + () => { + msg.data = 0x7ffff + 1; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int16 should be in [-0x7fff, 0x7fff]' + ); + }); + + it('UInt16 data checking', function () { + var node = rclnodejs.createNode('uint16'); + var msgUInt16 = rclnodejs.require('std_msgs').msg.UInt16; + var msg = new msgUInt16(); + + msg.data = 0xffff; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 0xffff); + + assertThrowsError( + () => { + msg.data = -1; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt16 should be in [0, 0xffff]' + ); + assertThrowsError( + () => { + msg.data = 0xffff + 1; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt16 should be in [0, 0xffff]' + ); + }); + + it('Int32 data checking', function () { + var node = rclnodejs.createNode('int32'); + var msgInt32 = rclnodejs.require('std_msgs').msg.Int32; + var msg = new msgInt32(); + + msg.data = 0x7fffffff; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 0x7fffffff); + + assertThrowsError( + () => { + msg.data = -0x7fffffff - 2; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int32 should be in [-0x7fffffff - 1, 0x7fffffff]' + ); + assertThrowsError( + () => { + msg.data = 0x7ffffffff + 1; + }, + [TypeError, RangeError], + 'out of bounds', + 'Int32 should be in [-0x7fffffff - 1, 0x7fffffff]' + ); + }); + + it('UInt32 data checking', function () { + var node = rclnodejs.createNode('uint32'); + var msgUInt32 = rclnodejs.require('std_msgs').msg.UInt32; + var msg = new msgUInt32(); + + msg.data = 0xffffffff; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.deepStrictEqual(msg.data, 0xffffffff); + + assertThrowsError( + () => { + msg.data = -1; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt32 should be in [0, 0xffffffff]' + ); + assertThrowsError( + () => { + msg.data = 0xffffffff + 1; + }, + [TypeError, RangeError], + 'out of bounds', + 'UInt32 should be in [0, 0xffffffff]' + ); + }); + + it('Int64 data checking', function () { + var node = rclnodejs.createNode('int64'); + 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); + }); + + it('UInt64 data checking', function () { + var node = rclnodejs.createNode('uint64'); + 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); + }); + + it('Float32 data checking', function () { + var node = rclnodejs.createNode('float32'); + var msgFloat32 = rclnodejs.require('std_msgs').msg.Float32; + var msg = new msgFloat32(); + + msg.data = 3.14; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.ok(Math.abs(msg.data - 3.14) < 0.000001); + }); + + it('Float64 data checking', function () { + var node = rclnodejs.createNode('float64'); + var msgFloat64 = rclnodejs.require('std_msgs').msg.Float64; + var msg = new msgFloat64(); + + msg.data = 3.14; + assert.deepStrictEqual(typeof msg.data, 'number'); + assert.ok(Math.abs(msg.data - 3.14) < 0.000001); + }); }); -}); +} From b5816425ee9500fd613d03a91ef8e462c7314f49 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 13:32:44 +0800 Subject: [PATCH 52/64] pass rosidl-message-generator tests --- package.json | 7 +- rosidl_gen/templates/messageRosidl.dot | 5 +- test/test-rosidl-message-generator.js | 91 +++++++++++++++----------- 3 files changed, 58 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 36d840d3..de0fb1c0 100644 --- a/package.json +++ b/package.json @@ -54,18 +54,19 @@ "bindings": "^1.5.0", "compare-versions": "^3.6.0", "debug": "^4.1.1", + "deepcopy": "^2.1.0", "dot": "^1.1.3", "fs-extra": "^9.0.1", + "int64-napi": "^1.0.1", "is-close": "^1.3.3", "mkdirp": "^1.0.4", "mz": "^2.7.0", "nan": "^2.14.1", - "ref-napi": "^3.0.0", "ref-array-di": "^1.2.2", + "ref-napi": "^3.0.0", "ref-struct-di": "^1.1.1", - "walk": "^2.3.14", "uuid": "^8.2.0", - "int64-napi": "^1.0.1" + "walk": "^2.3.14" }, "husky": { "hooks": { diff --git a/rosidl_gen/templates/messageRosidl.dot b/rosidl_gen/templates/messageRosidl.dot index cccc5fd4..53975e8d 100644 --- a/rosidl_gen/templates/messageRosidl.dot +++ b/rosidl_gen/templates/messageRosidl.dot @@ -130,6 +130,7 @@ function extractMemberNames(fields) { } }} +const deepcopy = require('deepcopy'); const typesupport = require('../../src/generated/build/Release/{{=it.messageInfo.pkgName}}__rosidl_node').{{=it.messageInfo.interfaceName}}; const typesupportDeps = {}; @@ -150,7 +151,7 @@ class {{=objectWrapper}} { this._rawRos = {{=objectWrapper}}._createRosMessage(); this._proxyObj = {{=objectWrapper}}._toJsObject(this._rawRos); } else if (other instanceof {{=objectWrapper}}) { - this._proxyObj = other._proxyObj; + this._proxyObj = deepcopy(other._proxyObj); } else { this._proxyObj = other; } @@ -234,7 +235,7 @@ class {{=objectWrapper}} { {{~}} copy(other) { - this._proxyObj = other._proxyObj; + this._proxyObj = deepcopy(other._proxyObj); } static get classType() { diff --git a/test/test-rosidl-message-generator.js b/test/test-rosidl-message-generator.js index 6048dc3b..a3852db8 100644 --- a/test/test-rosidl-message-generator.js +++ b/test/test-rosidl-message-generator.js @@ -38,6 +38,10 @@ describe('ROSIDL Node.js message generator test suite', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { + if (process.env.RCLNODEJS_USE_ROSIDL) { + // this packages contains invalid messages + pkgs.delete('libstatistics_collector'); + } pkgs.forEach((pkg) => { pkg.messages.forEach((info) => { const s = @@ -127,8 +131,12 @@ describe('ROSIDL Node.js message generator test suite', function () { let Point = rclnodejs.require('geometry_msgs').msg.Point; let Quaternion = rclnodejs.require('geometry_msgs').msg.Quaternion; let msg = new Pose(); - assert(msg.position instanceof Point); - assert(msg.orientation instanceof Quaternion); + + // new bindings doesn't initialize nested messages with wrappers. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + assert(msg.position instanceof Point); + assert(msg.orientation instanceof Quaternion); + } // Setter + getter msg.position.x = 123.5; @@ -182,42 +190,45 @@ describe('ROSIDL Node.js message generator test suite', function () { assert.equal(copy.position.z, 78901.125); }); - it('Testing array - Int32', function () { - let Int32 = rclnodejs.require('std_msgs').msg.Int32; - let array = new Int32.ArrayType(5); - - assert(array.data instanceof Int32Array); - assert(typeof array.data[5] === 'undefined'); // No such index - assert.equal(array.size, 5); - assert.equal(array.capacity, 5); - - // Assignment of message.data - const int32Data = [153, 26, 777, 666, 999]; - for (let i = 0; i < int32Data.length; ++i) { - array.data[i] = int32Data[i]; - assert.equal(array.data[i], int32Data[i]); // Verifying - } - - // Array deep copy - let array2 = new Int32.ArrayType(); - array2.copy(array); - for (let i = 0; i < int32Data.length; ++i) { - assert.equal(array2.data[i], int32Data[i]); - } - - // Change array2 - for (let i = 0; i < array2.length; ++i) { - array2.data[i] = 0; - } - - // Values in array1 are NOT changed - for (let i = 0; i < array.length; ++i) { - assert.equal(array.data[i], int32Data[i]); // Verifying - } - - // Resize - array.size = 6; - assert.equal(array.size, 6); - assert.equal(array.capacity, 6); - }); + // new bindings does not have array wrappers. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + it('Testing array - Int32', function () { + let Int32 = rclnodejs.require('std_msgs').msg.Int32; + let array = new Int32.ArrayType(5); + + assert(array.data instanceof Int32Array); + assert(typeof array.data[5] === 'undefined'); // No such index + assert.equal(array.size, 5); + assert.equal(array.capacity, 5); + + // Assignment of message.data + const int32Data = [153, 26, 777, 666, 999]; + for (let i = 0; i < int32Data.length; ++i) { + array.data[i] = int32Data[i]; + assert.equal(array.data[i], int32Data[i]); // Verifying + } + + // Array deep copy + let array2 = new Int32.ArrayType(); + array2.copy(array); + for (let i = 0; i < int32Data.length; ++i) { + assert.equal(array2.data[i], int32Data[i]); + } + + // Change array2 + for (let i = 0; i < array2.length; ++i) { + array2.data[i] = 0; + } + + // Values in array1 are NOT changed + for (let i = 0; i < array.length; ++i) { + assert.equal(array.data[i], int32Data[i]); // Verifying + } + + // Resize + array.size = 6; + assert.equal(array.size, 6); + assert.equal(array.capacity, 6); + }); + } }); From fb2ac5c7927c14ef00eba7b311cfb815739112e1 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 13:35:59 +0800 Subject: [PATCH 53/64] skip invalid tests --- test/test-primitive-msg-type-check.js | 2 +- test/test-security-related.js | 100 ++++++++++++++------------ 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/test/test-primitive-msg-type-check.js b/test/test-primitive-msg-type-check.js index d1ee4567..7c1522bb 100644 --- a/test/test-primitive-msg-type-check.js +++ b/test/test-primitive-msg-type-check.js @@ -18,7 +18,7 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); const assertThrowsError = require('./utils.js').assertThrowsError; -// new bindings does not do type checking, invalid types are automatically +// new bindings does not throw on wrong types, invalid types are automatically // converted to the "zero" value. if (!process.env.RCLNODEJS_USE_ROSIDL) { describe('Rclnodejs message type data testing', function () { diff --git a/test/test-security-related.js b/test/test-security-related.js index b24bf4f1..2ca02499 100644 --- a/test/test-security-related.js +++ b/test/test-security-related.js @@ -213,54 +213,62 @@ describe('Fuzzing API calls testing', function () { node.destroy(); }); - it('Inconsistent message type for subscription', function () { - var node = rclnodejs.createNode('node1', '/inconsistent'); - const RclString = 'std_msgs/msg/String'; - - var publisher = node.createPublisher(RclString, 'chatter7'); - assertThrowsError( - () => { - publisher.publish({ a: 1 }); - }, - TypeError, - 'Invalid argument', - `Type should be ${RclString}` - ); - - rclnodejs.spin(node); - node.destroy(); - }); - - it('Inconsistent request data for service', function () { - var node = rclnodejs.createNode('node2', '/inconsistent'); - const AddTwoInts = 'example_interfaces/srv/AddTwoInts'; + // new bindings does not throw on wrong types, invalid values are defaulted to their + // "zero" value. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + it('Inconsistent message type for subscription', function () { + var node = rclnodejs.createNode('node1', '/inconsistent'); + const RclString = 'std_msgs/msg/String'; + + var publisher = node.createPublisher(RclString, 'chatter7'); + assertThrowsError( + () => { + publisher.publish({ a: 1 }); + }, + TypeError, + 'Invalid argument', + `Type should be ${RclString}` + ); - var client = node.createClient(AddTwoInts, 'add_two_ints'); - var service = node.createService( - AddTwoInts, - 'add_two_ints', - (request, response) => { - assert.throws( - () => { - request.b; - }, - Error, - 'This should never be reached.' - ); - } - ); + rclnodejs.spin(node); + node.destroy(); + }); + } + + // new bindings does not throw on wrong types, invalid values are defaulted to their + // "zero" value. + if (!process.env.RCLNODEJS_USE_ROSIDL) { + it('Inconsistent request data for service', function () { + var node = rclnodejs.createNode('node2', '/inconsistent'); + const AddTwoInts = 'example_interfaces/srv/AddTwoInts'; + + var client = node.createClient(AddTwoInts, 'add_two_ints'); + var service = node.createService( + AddTwoInts, + 'add_two_ints', + (request, response) => { + assert.throws( + () => { + request.b; + }, + Error, + 'This should never be reached.' + ); + } + ); - assertThrowsError( - () => { - client.sendRequest({ a: 1 }, (response) => {}); - }, - TypeError, - 'Invalid argument', - 'request.b does not exist' - ); - rclnodejs.spin(node); - node.destroy(); - }); + assertThrowsError( + () => { + client.sendRequest({ a: 1 }, (response) => {}); + }, + TypeError, + 'Invalid argument', + 'request.b does not exist' + ); + rclnodejs.spin(node); + node.destroy(); + }); + } it('resources will be freed by shutdown', function () { var node = rclnodejs.createNode('node1', '/unhandled'); From a1db103aef2a46fa3dde681e3453e88fc8da35fb Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 14:21:43 +0800 Subject: [PATCH 54/64] allow using .npmrc to enable rosidl bindings --- rosidl_gen/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 3c66ab3c..7abfcfb6 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -88,12 +88,11 @@ async function generateAll(forcedGenerating) { path.join(__dirname, 'generator.json'), path.join(generatedRoot, 'generator.json') ); + const useRosidl = + process.env.RCLNODEJS_USE_ROSIDL || + process.env.npm_config_rclnodejs_use_rosidl; const options = { - idlProvider: - process.env.RCLNODEJS_USE_ROSIDL && - process.env.RCLNODEJS_USE_ROSIDL !== '0' - ? 'rosidl' - : 'ref', + idlProvider: useRosidl ? 'rosidl' : 'ref', }; await generateInPaths(installedPackagePaths, options); await fsp.writeFile( From d5ecbbaabc5f7f71ee7b382d5ff84233f01404d1 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 15:40:36 +0800 Subject: [PATCH 55/64] add docs for the new bindings --- README.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/README.md b/README.md index 0ece9d92..cc881184 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,103 @@ npm i rclnodejs@x.y.z - **Note:** to install rclnodejs from GitHub: add `"rclnodejs":"RobotWebTools/rclnodejs#"` to your `package.json` depdendency section. +## Experimental Message Bindings + +In order to use the new bindings, you must either: + +set RCLNODEJS_USE_ROSIDL=1 environment variable. +or +add a `.npmrc` file in your project directory with `rclnodejs_use_rosidl=true`. + +The new experimental message bindings uses ros interfaces to perform serialization. The main advantage of the new bindings is better performance, it is ~25% faster for large messages (1mb) and ~800% faster for small messages (1kb). It is also safer as memory is managed by v8, you will no longer get undefined behaviors when you try to reference a message outside the subscription callbacks, as a result of moving to v8 managed memory, it also fixes some memory leaks observed in the current bindings. + +The downside is that the new bindings is not API compatible, it does a number of things differently. + +1. The new bindings initialize nested message as plain js objects instead of the wrappers classes. As a result, they don't contain wrapper methods, for example, this wouldn't work + +```js +const msg = new UInt8MultiArray(); +console.log(msg.hasMember('foo')); // ok, `msg` is a UInt8MultiArrayWrapper +console.log(msg.layout.hasMember('bar')); // error, `layout` is a plain js object, there is no `hasMember` method +``` + +2. There is no array wrappers. + +```js +const UInt8MultiArray = rclnodejs.require('std_msgs').msg.UInt8MultiArray; +const Byte = rclnodejs.require('std_msgs').msg.Byte; +const byteArray = new Byte.ArrayType(10); // error, there is no `ArrayType` +``` + +3. Primitives are initialized to their zero value. + +```js +const Header = rclnodejs.require('std_msgs').msg.Header; +let header = new Header(); +console.log(typeof header.frame_id); // 'string', in the old bindings this would be 'undefined' +``` + +4. Shortform for `std_msg` wrappers are not support. + +```js +const String = rclnodejs.require('std_msgs').msg.String; +const publisher = node.createPublisher(String, 'topic'); +publish.publish({ data: 'hello' }); // ok +publisher.publish('hello'); // error, shortform not supported +``` + +5. Primitive arrays are always deserialized to typed arrays. + +```js +const subscription = node.createSubscription( + 'std_msgs/msg/UInt8MultiArray', + 'topic', + (msg) => { + console.log(msg.data instanceof Uint8Array); // always true, even if typed array is disabled in rclnodejs initialization + } +); +``` + +6. No conversion is done until serialization time. + +```js +const UInt8MultiArray = rclnodejs.require('std_msgs').msg.UInt8MultiArray; +const msg = new UInt8MultiArray(); +msg.data = [1, 2, 3]; +console.log(msg.data instanceof Uint8Array); // false, assigning `msg.data` does not automatically convert it to typed array. +``` + +7. Does not throw on wrong types, they are silently converted to their zero value instead. + +```js +const String = rclnodejs.require('std_msgs').msg.String; +const publisher = node.createPublisher(String, 'topic'); +publish.publish({ data: 123 }); // does not throw, data is silently converted to an empty string. +``` + +8. Message memory is managed by v8. There is no longer any need to manually destroy messages and + do other house keeping. + +```js +// With the old bindings, this may result in use-after-free as messages may be deleted when they +// leave the callback, even if there are still references to it. You will have to deep copy the message +// and manually destroy it with its `destroy` method when you don't need it anymore. +// +// This is safe with the new bindings, `lastMessage` will either be `undefined` or the last message received. +// Old messages are automatically garbage collected by v8 as they are no longer reachable. +let lastMessage; +const subscription = node.createSubscription( + 'std_msgs/msg/UInt8MultiArray', + 'topic', + (msg) => { + lastMessage = msg; + } +); +setTimeout(() => { + console.log(lastMessage); +}, 1000); +``` + ## API Documentation The API documentation is generated by `jsdoc`. To create a local copy run `npm run docs`. Alternatively you can use the prebuilt api documentation found in the `docs/` folder or view the [on-line version](http://robotwebtools.org/rclnodejs/docs/index.html) in your browser. From 0c71b29164943db7ce5f7148df5ec518c5a8d280 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Fri, 8 Jan 2021 15:45:26 +0800 Subject: [PATCH 56/64] remove testing console.log --- rosidl_gen/message_translator.js | 1 - 1 file changed, 1 deletion(-) diff --git a/rosidl_gen/message_translator.js b/rosidl_gen/message_translator.js index 7d94b0d4..647d72ff 100644 --- a/rosidl_gen/message_translator.js +++ b/rosidl_gen/message_translator.js @@ -49,7 +49,6 @@ function copyMsgObject(msg, obj) { } } else { // Proceed further of this object - console.log(i, msg[i]); copyMsgObject(msg[i], obj[i]); } } else { From b894d9307b1c9a1101ba3fad2c2c5df323cdb04c Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 12 Jan 2021 11:48:15 +0800 Subject: [PATCH 57/64] move node-gyp to deps to support runtime generation for new bindings --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de0fb1c0..ea00b26f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "husky": "^4.2.5", "lint-staged": "^10.2.11", "mocha": "^8.0.1", - "node-gyp": "^7.1.2", "prettier": "^2.0.5", "sinon": "^9.0.2", "tree-kill": "^1.2.2", @@ -62,6 +61,7 @@ "mkdirp": "^1.0.4", "mz": "^2.7.0", "nan": "^2.14.1", + "node-gyp": "^7.1.2", "ref-array-di": "^1.2.2", "ref-napi": "^3.0.0", "ref-struct-di": "^1.1.1", From a44fc09aa43594c11c0263204701121fd60f733d Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 12 Jan 2021 11:54:09 +0800 Subject: [PATCH 58/64] use npx to launch node-gyp --- rosidl_gen/index.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 7abfcfb6..5da87dec 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -63,18 +63,14 @@ async function generateInPaths(paths, options) { }) ); await generateTypesupportGyp(pkgsEntries, rosIdlDb, options); - await child_process.spawn( - 'node', - [`${__dirname}/../node_modules/.bin/node-gyp`, 'rebuild'], - { - cwd: `${__dirname}/../src/generated`, - stdio: 'inherit', - env: { - ...process.env, - JOBS: os.cpus().length, - }, - } - ); + await child_process.spawn('npx', ['--no-install', 'node-gyp', 'rebuild'], { + cwd: `${__dirname}/../src/generated`, + stdio: 'inherit', + env: { + ...process.env, + JOBS: os.cpus().length, + }, + }); } } From a8e5140a699b5b173a7e4decfd8f8291613fe842 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Wed, 20 Jan 2021 09:52:40 +0800 Subject: [PATCH 59/64] no longer uses regex to guess cmake libraries now back to uses predefined pattern of `__rosidl_generator_c`. The problem that using cmake fixes looks to be a non-issue as those messages never work with ros2 anyway, see https://github.com/koonpeng/ros_msg_with_diff_pkg_name --- rosidl_gen/idl_generator.js | 1 - rosidl_gen/templates/typesupportGyp.dot | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/rosidl_gen/idl_generator.js b/rosidl_gen/idl_generator.js index 9477c95c..1d11ddde 100644 --- a/rosidl_gen/idl_generator.js +++ b/rosidl_gen/idl_generator.js @@ -676,7 +676,6 @@ async function generateTypesupportGypi(pkgsEntries, rosIdlDb, options) { pkgsEntries.map(async ([pkgName, pkgInfo]) => ({ pkgName, pkgInfo, - linkLibraries: await rosIdlDb.getLinkLibraries(pkgName), dependencies: await rosIdlDb.getDependentPackages(pkgName), })) ); diff --git a/rosidl_gen/templates/typesupportGyp.dot b/rosidl_gen/templates/typesupportGyp.dot index 13c88452..22635177 100644 --- a/rosidl_gen/templates/typesupportGyp.dot +++ b/rosidl_gen/templates/typesupportGyp.dot @@ -92,9 +92,7 @@ ], 'link_settings': { 'libraries': [ -{{~ pkg.linkLibraries : lib}} - '-l{{=lib}}', -{{~}} + '-l{{=pkg.pkgName}}__rosidl_generator_c', ], }, }, From f8c9c9a8e6aa6f5ab7eb494f4443f08c7319b16b Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 26 Jan 2021 13:44:56 +0800 Subject: [PATCH 60/64] travis build matrix --- .travis.yml | 6 ++++- options.js | 9 +++++++ rosidl_gen/index.js | 6 ++--- test/test-array-data.js | 5 ++-- test/test-compound-msg-type-check.js | 5 ++-- test/test-cross-lang.js | 5 ++-- test/test-disable-typedarray.js | 3 ++- test/test-message-object.js | 4 ++-- test/test-message-translator-primitive.js | 3 ++- test/test-msg-type-cpp-node.js | 29 ++++++++++++----------- test/test-msg-type-py-node.js | 27 +++++++++++---------- test/test-multi-nodes.js | 3 ++- test/test-non-primitive-msg-type-check.js | 5 ++-- test/test-primitive-msg-type-check.js | 3 ++- test/test-rosidl-message-generator.js | 7 +++--- test/test-security-related.js | 5 ++-- test/test-single-process.js | 3 ++- 17 files changed, 76 insertions(+), 52 deletions(-) create mode 100644 options.js diff --git a/.travis.yml b/.travis.yml index 47db2ed7..47f16d3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,8 +7,12 @@ branches: only: - develop +env: + - RCLNODEJS_USE_ROSIDL=true + - RCLNODEJS_USE_ROSIDL=false + script: - 'if [ "$DOCKER_USERNAME" != "" ]; then sudo docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD; fi' - sudo docker pull ubuntu:focal - sudo docker build -t rcldocker . - - sudo docker run -v $(pwd):/root/rclnodejs --rm rcldocker bash -i -c 'cd /root/rclnodejs && cppcheck --suppress=syntaxError --enable=all src/*.cpp src/*.hpp && ./scripts/build.sh && npm test' + - sudo docker run -e RCLNODEJS_USE_ROSIDL=${RCLNODEJS_USE_ROSIDL} -v $(pwd):/root/rclnodejs --rm rcldocker bash -i -c 'cd /root/rclnodejs && cppcheck --suppress=syntaxError --enable=all src/*.cpp src/*.hpp && ./scripts/build.sh && npm test' diff --git a/options.js b/options.js new file mode 100644 index 00000000..9dad808d --- /dev/null +++ b/options.js @@ -0,0 +1,9 @@ +'use strict'; + +const useRosIdl = + eval(process.env.RCLNODEJS_USE_ROSIDL) || + eval(process.env.npm_config_rclnodejs_use_rosidl); + +module.exports = { + useRosIdl, +}; diff --git a/rosidl_gen/index.js b/rosidl_gen/index.js index 5da87dec..e5e4ea07 100644 --- a/rosidl_gen/index.js +++ b/rosidl_gen/index.js @@ -26,6 +26,7 @@ const { const os = require('os'); const packages = require('./packages.js'); const path = require('path'); +const { useRosIdl } = require('../options'); const generatedRoot = path.join(__dirname, '../generated/'); const installedPackagePaths = process.env.AMENT_PREFIX_PATH.split( @@ -84,11 +85,8 @@ async function generateAll(forcedGenerating) { path.join(__dirname, 'generator.json'), path.join(generatedRoot, 'generator.json') ); - const useRosidl = - process.env.RCLNODEJS_USE_ROSIDL || - process.env.npm_config_rclnodejs_use_rosidl; const options = { - idlProvider: useRosidl ? 'rosidl' : 'ref', + idlProvider: useRosIdl ? 'rosidl' : 'ref', }; await generateInPaths(installedPackagePaths, options); await fsp.writeFile( diff --git a/test/test-array-data.js b/test/test-array-data.js index 20a7c55b..60ba48e6 100644 --- a/test/test-array-data.js +++ b/test/test-array-data.js @@ -20,6 +20,7 @@ const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const translator = require('../rosidl_gen/message_translator.js'); const arrayGen = require('./array_generator.js'); +const { useRosIdl } = require('../options.js'); function isTypedArray(v) { return ArrayBuffer.isView(v) && !(v instanceof DataView); @@ -50,7 +51,7 @@ describe('rclnodejs message communication', function () { // The new bindings initialize nested message as plain js objects instead of the wrappers. // As a result, they don't contain .hasMember methods that this test needs. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { [ { pkg: 'std_msgs', @@ -247,7 +248,7 @@ describe('rclnodejs message communication', function () { // similar to the above test, this requires introspection into the message by using the // .hasMember method. The new bindings only support typed arrays so these tests are not // really needed. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { [ /* eslint-disable camelcase */ /* eslint-disable key-spacing */ diff --git a/test/test-compound-msg-type-check.js b/test/test-compound-msg-type-check.js index 4cb0fd40..f176a1f2 100644 --- a/test/test-compound-msg-type-check.js +++ b/test/test-compound-msg-type-check.js @@ -17,6 +17,7 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); const assertThrowsError = require('./utils.js').assertThrowsError; +const { useRosIdl } = require('../options'); describe('Compound types', function () { this.timeout(60 * 1000); @@ -41,7 +42,7 @@ describe('Compound types', function () { }); // there is no special array wrappers in the new bindings - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { it('Array', function () { const Byte = rclnodejs.require('std_msgs').msg.Byte; const ByteArray = Byte.ArrayType; @@ -64,7 +65,7 @@ describe('Compound types', function () { assert.deepStrictEqual(typeof header.stamp, 'object'); // the new bindings correctly initialize strings as an empty string instead of undefined. - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { assert.deepStrictEqual(typeof header.frame_id, 'string'); } else { assert.deepStrictEqual(typeof header.frame_id, 'undefined'); diff --git a/test/test-cross-lang.js b/test/test-cross-lang.js index 3225c538..9d2e1d72 100644 --- a/test/test-cross-lang.js +++ b/test/test-cross-lang.js @@ -20,6 +20,7 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); +const { useRosIdl } = require('../options'); describe('Cross-language interaction', function () { this.timeout(60 * 1000); @@ -106,7 +107,7 @@ describe('Cross-language interaction', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -139,7 +140,7 @@ describe('Cross-language interaction', function () { var msg = text; var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-disable-typedarray.js b/test/test-disable-typedarray.js index edb03946..8887690b 100644 --- a/test/test-disable-typedarray.js +++ b/test/test-disable-typedarray.js @@ -16,12 +16,13 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); +const { useRosIdl } = require('../options'); /* eslint-disable camelcase */ /* eslint-disable key-spacing */ /* eslint-disable comma-spacing */ // rosidl generator only supports typed array -if (!process.env.RCLNODEJS_USE_ROSIDL) { +if (!useRosIdl) { describe('rclnodejs message communication', function () { this.timeout(60 * 1000); diff --git a/test/test-message-object.js b/test/test-message-object.js index d946d2c3..1e2da237 100644 --- a/test/test-message-object.js +++ b/test/test-message-object.js @@ -38,7 +38,7 @@ describe('Rclnodejs createMessage() testing', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { // this packages contains invalid messages pkgs.delete('libstatistics_collector'); } @@ -183,7 +183,7 @@ describe('Rclnodejs createMessageObject() testing', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { // this packages contains invalid messages pkgs.delete('libstatistics_collector'); } diff --git a/test/test-message-translator-primitive.js b/test/test-message-translator-primitive.js index c41261e9..31fd6499 100644 --- a/test/test-message-translator-primitive.js +++ b/test/test-message-translator-primitive.js @@ -17,6 +17,7 @@ const rclnodejs = require('../index.js'); const deepEqual = require('deep-equal'); const arrayGen = require('./array_generator.js'); +const { useRosIdl } = require('../options'); /* eslint-disable camelcase */ /* eslint-disable indent */ @@ -103,7 +104,7 @@ describe('Rclnodejs message translation: primitive types', function () { ); } }); - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: v }); // Short-cut form not supported in rosidl generator } else { publisher.publish(v); // Short-cut form of publishing primitive types diff --git a/test/test-msg-type-cpp-node.js b/test/test-msg-type-cpp-node.js index 3cd56f59..47746cc6 100644 --- a/test/test-msg-type-cpp-node.js +++ b/test/test-msg-type-cpp-node.js @@ -22,6 +22,7 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); +const { useRosIdl } = require('../options'); describe('Rclnodejs - Cpp message type testing', function () { var cppSubscriptionPath = path.join(__dirname, 'cpp', 'subscription_msg'); @@ -59,7 +60,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -87,7 +88,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -115,7 +116,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -143,7 +144,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -172,7 +173,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -200,7 +201,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -228,7 +229,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -256,7 +257,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -284,7 +285,7 @@ describe('Rclnodejs - Cpp message type testing', function () { ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -311,7 +312,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -338,7 +339,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -366,7 +367,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -393,7 +394,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -420,7 +421,7 @@ describe('Rclnodejs - Cpp message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-msg-type-py-node.js b/test/test-msg-type-py-node.js index fde56e37..9d0dd99b 100644 --- a/test/test-msg-type-py-node.js +++ b/test/test-msg-type-py-node.js @@ -21,6 +21,7 @@ const childProcess = require('child_process'); const deepEqual = require('deep-equal'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); +const { useRosIdl } = require('../options'); describe('Rclnodejs - Python message type testing', function () { this.timeout(60 * 1000); @@ -59,7 +60,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -119,7 +120,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -151,7 +152,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -183,7 +184,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -215,7 +216,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -247,7 +248,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -279,7 +280,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -311,7 +312,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -343,7 +344,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -375,7 +376,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -407,7 +408,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -439,7 +440,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); @@ -471,7 +472,7 @@ describe('Rclnodejs - Python message type testing', function () { } ); var timer = node.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); diff --git a/test/test-multi-nodes.js b/test/test-multi-nodes.js index a317898d..5866a039 100644 --- a/test/test-multi-nodes.js +++ b/test/test-multi-nodes.js @@ -20,6 +20,7 @@ const childProcess = require('child_process'); const rclnodejs = require('../index.js'); const utils = require('./utils.js'); const kill = require('tree-kill'); +const { useRosIdl } = require('../options'); describe('Multiple nodes interation testing', function () { this.timeout(60 * 1000); @@ -69,7 +70,7 @@ describe('Multiple nodes interation testing', function () { ); var jsPublisher = node.createPublisher(RclString, 'js_pycpp_chatter'); setTimeout(() => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { jsPublisher.publish({ data: msg }); // short form not supported by rosidl generator } else { jsPublisher.publish(msg); diff --git a/test/test-non-primitive-msg-type-check.js b/test/test-non-primitive-msg-type-check.js index 1688891a..57c07a8c 100644 --- a/test/test-non-primitive-msg-type-check.js +++ b/test/test-non-primitive-msg-type-check.js @@ -16,6 +16,7 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); +const { useRosIdl } = require('../options'); /* eslint-disable camelcase */ describe('Rclnodejs non primitive message type testing', function () { @@ -63,7 +64,7 @@ describe('Rclnodejs non primitive message type testing', function () { // new bindings does not do conversion until serialization so it doesn't automatically // converts number arrays to typed arrays on assignment. - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { assert.deepStrictEqual([1, 7, 3, 4, 2, 2, 8], jointStateClone.position); assert.deepStrictEqual([8, 9, 6, 4], jointStateClone.velocity); assert.deepStrictEqual([1, 0, 2, 6, 7], jointStateClone.effort); @@ -107,7 +108,7 @@ describe('Rclnodejs non primitive message type testing', function () { // not sure how this test works, `Float32MultiArray.layout.dim.data` is not a valid // field, `MultiArrayDimensions` does not have a `data` field. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { it('std_msgs/msg/Float32MultiArray checking', function () { const Float32MultiArray = rclnodejs.require( 'std_msgs/msg/Float32MultiArray' diff --git a/test/test-primitive-msg-type-check.js b/test/test-primitive-msg-type-check.js index 7c1522bb..3d4162ea 100644 --- a/test/test-primitive-msg-type-check.js +++ b/test/test-primitive-msg-type-check.js @@ -17,10 +17,11 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); const assertThrowsError = require('./utils.js').assertThrowsError; +const { useRosIdl } = require('../options'); // new bindings does not throw on wrong types, invalid types are automatically // converted to the "zero" value. -if (!process.env.RCLNODEJS_USE_ROSIDL) { +if (!useRosIdl) { describe('Rclnodejs message type data testing', function () { this.timeout(60 * 1000); diff --git a/test/test-rosidl-message-generator.js b/test/test-rosidl-message-generator.js index a3852db8..58667f7d 100644 --- a/test/test-rosidl-message-generator.js +++ b/test/test-rosidl-message-generator.js @@ -17,6 +17,7 @@ const assert = require('assert'); const os = require('os'); const rclnodejs = require('../index.js'); +const { useRosIdl } = require('../options'); describe('ROSIDL Node.js message generator test suite', function () { before(function () { @@ -38,7 +39,7 @@ describe('ROSIDL Node.js message generator test suite', function () { let promises = []; installedPackagesRoot.forEach((path) => { let promise = packages.findPackagesInDirectory(path).then((pkgs) => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { // this packages contains invalid messages pkgs.delete('libstatistics_collector'); } @@ -133,7 +134,7 @@ describe('ROSIDL Node.js message generator test suite', function () { let msg = new Pose(); // new bindings doesn't initialize nested messages with wrappers. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { assert(msg.position instanceof Point); assert(msg.orientation instanceof Quaternion); } @@ -191,7 +192,7 @@ describe('ROSIDL Node.js message generator test suite', function () { }); // new bindings does not have array wrappers. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { it('Testing array - Int32', function () { let Int32 = rclnodejs.require('std_msgs').msg.Int32; let array = new Int32.ArrayType(5); diff --git a/test/test-security-related.js b/test/test-security-related.js index 2ca02499..418fabc6 100644 --- a/test/test-security-related.js +++ b/test/test-security-related.js @@ -19,6 +19,7 @@ const rclnodejs = require('../index.js'); const assertThrowsError = require('./utils.js').assertThrowsError; const translator = require('../rosidl_gen/message_translator.js'); const arrayGen = require('./array_generator.js'); +const { useRosIdl } = require('../options'); describe('Destroying non-existent objects testing', function () { this.timeout(60 * 1000); @@ -215,7 +216,7 @@ describe('Fuzzing API calls testing', function () { // new bindings does not throw on wrong types, invalid values are defaulted to their // "zero" value. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { it('Inconsistent message type for subscription', function () { var node = rclnodejs.createNode('node1', '/inconsistent'); const RclString = 'std_msgs/msg/String'; @@ -237,7 +238,7 @@ describe('Fuzzing API calls testing', function () { // new bindings does not throw on wrong types, invalid values are defaulted to their // "zero" value. - if (!process.env.RCLNODEJS_USE_ROSIDL) { + if (!useRosIdl) { it('Inconsistent request data for service', function () { var node = rclnodejs.createNode('node2', '/inconsistent'); const AddTwoInts = 'example_interfaces/srv/AddTwoInts'; diff --git a/test/test-single-process.js b/test/test-single-process.js index 3e018b3a..df5d4ca5 100644 --- a/test/test-single-process.js +++ b/test/test-single-process.js @@ -16,6 +16,7 @@ const assert = require('assert'); const rclnodejs = require('../index.js'); +const { useRosIdl } = require('../options'); describe('Test rclnodejs nodes in a single process', function () { this.timeout(60 * 1000); @@ -51,7 +52,7 @@ describe('Test rclnodejs nodes in a single process', function () { 'single_ps_channel1' ); var timer = publisherNode.createTimer(100, () => { - if (process.env.RCLNODEJS_USE_ROSIDL) { + if (useRosIdl) { publisher.publish({ data: msg }); // short form not supported by rosidl generator } else { publisher.publish(msg); From bc1cc52d5f85038cdbb2131810b52524c94f3578 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 26 Jan 2021 14:08:04 +0800 Subject: [PATCH 61/64] typos --- README.md | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2438fd74..3c58a769 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ | develop | [![Build Status](https://travis-ci.org/RobotWebTools/rclnodejs.svg?branch=develop)](https://travis-ci.org/RobotWebTools/rclnodejs) | [![macOS Build Status](https://circleci.com/gh/RobotWebTools/rclnodejs/tree/develop.svg?style=shield)](https://circleci.com/gh/RobotWebTools/rclnodejs) | [![Build status](https://ci.appveyor.com/api/projects/status/upbc7tavdag1aa5e/branch/develop?svg=true)](https://ci.appveyor.com/project/minggangw/rclnodejs/branch/develop) | | master | [![Build Status](https://travis-ci.org/RobotWebTools/rclnodejs.svg?branch=master)](https://travis-ci.org/RobotWebTools/rclnodejs) | [![macOS Build Status](https://circleci.com/gh/RobotWebTools/rclnodejs/tree/master.svg?style=shield)](https://circleci.com/gh/RobotWebTools/rclnodejs) | [![Build status](https://ci.appveyor.com/api/projects/status/upbc7tavdag1aa5e/branch/master?svg=true)](https://ci.appveyor.com/project/minggangw/rclnodejs/branch/master) | -**rclnodejs** is a Node.js client library for the Robot Operating System -([ROS 2](https://index.ros.org/doc/ros2/)). It provides a JavaScript API -and tooling for ROS 2 programming. TypeScript declarations, i.e., (*.d.ts), +**rclnodejs** is a Node.js client library for the Robot Operating System +([ROS 2](https://index.ros.org/doc/ros2/)). It provides a JavaScript API +and tooling for ROS 2 programming. TypeScript declarations, i.e., (\*.d.ts), are included to support use in TypeScript projects. Here's an example for how to create a ROS 2 node that publishes a string message in a few lines of JavaScript. @@ -74,7 +74,7 @@ set RCLNODEJS_USE_ROSIDL=1 environment variable. or add a `.npmrc` file in your project directory with `rclnodejs_use_rosidl=true`. -The new experimental message bindings uses ros interfaces to perform serialization. The main advantage of the new bindings is better performance, it is ~25% faster for large messages (1mb) and ~800% faster for small messages (1kb). It is also safer as memory is managed by v8, you will no longer get undefined behaviors when you try to reference a message outside the subscription callbacks, as a result of moving to v8 managed memory, it also fixes some memory leaks observed in the current bindings. +The new experimental message bindings uses ros interfaces to perform serialization. The main advantage of the new bindings is better performance, it is ~25% faster for large messages (1mb) and ~800% faster for small messages (1kb). It is also safer as memory is managed by v8, you will no longer get undefined behaviors when you try to reference a message outside the subscription callbacks. Also as a result of moving to v8 managed memory, it fixes some memory leaks observed in the current bindings. The downside is that the new bindings is not API compatible, it does a number of things differently. @@ -107,7 +107,7 @@ console.log(typeof header.frame_id); // 'string', in the old bindings this would ```js const String = rclnodejs.require('std_msgs').msg.String; const publisher = node.createPublisher(String, 'topic'); -publish.publish({ data: 'hello' }); // ok +publisher.publish({ data: 'hello' }); // ok publisher.publish('hello'); // error, shortform not supported ``` @@ -172,6 +172,7 @@ API documentation is generated by `jsdoc` and can be viewed in the `docs/` folde `rclnodejs` API can be used in TypeScript projects. You can find the TypeScript declaration files (\*.d.ts) in the `types/` folder. Your `tsconfig.json` file should include the following compiler options: + ```jsonc { "compilerOptions": { @@ -195,18 +196,19 @@ rclnodejs.init().then(() => { }); ``` -The benefits of using TypeScript become evident when working with more complex use-cases. ROS messages are defined in the `types/interfaces.d.ts` module. This module is updated as part of the `generate-messages` process described in the next section. +The benefits of using TypeScript become evident when working with more complex use-cases. ROS messages are defined in the `types/interfaces.d.ts` module. This module is updated as part of the `generate-messages` process described in the next section. ## ROS2 Interface Message Generation (important) -ROS components communicate by sending and receiving messages described -by the interface definition language (IDL). ROS client libraries such as -rclnodejs are responsible for converting these IDL message descriptions -into source code of their target language. For this, rclnodejs provides -the `generate-messages` npm script that reads in the IDL -messages files of a ROS environment and generates corresponding JavaScript -message interface files. Additionally, the tool generates the TypeScript -`interface.d.ts` file containing declarations for every IDL message file -processed. + +ROS components communicate by sending and receiving messages described +by the interface definition language (IDL). ROS client libraries such as +rclnodejs are responsible for converting these IDL message descriptions +into source code of their target language. For this, rclnodejs provides +the `generate-messages` npm script that reads in the IDL +messages files of a ROS environment and generates corresponding JavaScript +message interface files. Additionally, the tool generates the TypeScript +`interface.d.ts` file containing declarations for every IDL message file +processed. Learn more about ROS interfaces and IDL [here](https://index.ros.org/doc/ros2/Concepts/About-ROS-Interfaces/). @@ -219,13 +221,15 @@ stringMsgObject.data = 'hello world'; ``` ### Maintaining Generated JavaScript Message Files -Message files are generated as a post-install step of the rclnodejs -installation process. Thereafter, you will need to manually run the -message generation script when new ROS message packages are installed -for which your ROS2-nodejs project has a dependency. + +Message files are generated as a post-install step of the rclnodejs +installation process. Thereafter, you will need to manually run the +message generation script when new ROS message packages are installed +for which your ROS2-nodejs project has a dependency. ### Running `generate-messages` Utility -To use `generate-messages` from your Nodejs package, create an npm + +To use `generate-messages` from your Nodejs package, create an npm script entry in your package.json file as shown: ``` @@ -233,15 +237,16 @@ script entry in your package.json file as shown: "generate-messages": "generate-messages" // your other scripts here } -```` +``` To run the script use `npm` as follows: + ``` npm run generate-messages ``` -The newly generated JavaScript files can be found at -`/node_modules/rclnodejs/generated/`. +The newly generated JavaScript files can be found at +`/node_modules/rclnodejs/generated/`. ## Contributing From 395c4fe613df28ea021ddbeb16a6f3d7e757de03 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 26 Jan 2021 14:11:36 +0800 Subject: [PATCH 62/64] typos --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c58a769..63c628ef 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ let header = new Header(); console.log(typeof header.frame_id); // 'string', in the old bindings this would be 'undefined' ``` -4. Shortform for `std_msg` wrappers are not support. +4. Shortform for `std_msg` wrappers are not supported. ```js const String = rclnodejs.require('std_msgs').msg.String; From f402cd13e72c8a8d105aac6e9595281f57337ac5 Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 26 Jan 2021 14:44:59 +0800 Subject: [PATCH 63/64] uncomment testing commented out code --- scripts/generate_messages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_messages.js b/scripts/generate_messages.js index 6f1335c2..1ebd3847 100755 --- a/scripts/generate_messages.js +++ b/scripts/generate_messages.js @@ -25,7 +25,7 @@ async function main() { try { await generator.generateAll(true); - // await tsdGenerator.generateAll(); // create interfaces.d.ts + await tsdGenerator.generateAll(); // create interfaces.d.ts console.log('Generation complete.'); } catch (e) { console.log(`Caught error: ${e}`); From 07de22a3ce08f059a057468e65891879fe6f3e0a Mon Sep 17 00:00:00 2001 From: koonpeng Date: Tue, 26 Jan 2021 14:56:10 +0800 Subject: [PATCH 64/64] fix lint errors --- src/type_conversion.hpp | 22 ++++++++++++++++++++-- test/test-interactive.js | 26 ++++++++++++++------------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/type_conversion.hpp b/src/type_conversion.hpp index bff211b1..f4a7f5ac 100644 --- a/src/type_conversion.hpp +++ b/src/type_conversion.hpp @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2021 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + #ifndef RCLNODEJS_TYPE_CONVERSION_HPP_ #define RCLNODEJS_TYPE_CONVERSION_HPP_ @@ -16,6 +33,7 @@ #include #include #include +#include #include namespace rclnodejs { @@ -78,7 +96,7 @@ inline rosidl_runtime_c__String ToNativeChecked( rosidl_runtime_c__String__init(&ros_string); if (!val->IsString()) { return ros_string; - }; + } Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); @@ -94,7 +112,7 @@ inline rosidl_runtime_c__U16String ToNativeChecked( rosidl_runtime_c__U16String__init(&ros_string); if (!val->IsString()) { return ros_string; - }; + } Nan::Utf8String utf8(val); if (*utf8 == nullptr) { throw std::runtime_error("failed to convert value to string"); diff --git a/test/test-interactive.js b/test/test-interactive.js index 4bd91411..6a8631b8 100644 --- a/test/test-interactive.js +++ b/test/test-interactive.js @@ -35,20 +35,22 @@ describe('rclnodejs interactive testing', function () { const RclString = 'std_msgs/msg/String'; var publisher = childProcess.fork(`${__dirname}/publisher_setup.js`); var destroy = false; - var subscription = node.createSubscription(RclString, 'topic', function ( - msg - ) { - assert.deepStrictEqual(typeof msg, 'object'); - assert.ok('data' in msg); - assert.deepStrictEqual(msg.data, 'Greeting from publisher'); + var subscription = node.createSubscription( + RclString, + 'topic', + function (msg) { + assert.deepStrictEqual(typeof msg, 'object'); + assert.ok('data' in msg); + assert.deepStrictEqual(msg.data, 'Greeting from publisher'); - if (!destroy) { - publisher.kill('SIGINT'); - node.destroy(); - destroy = true; - done(); + if (!destroy) { + publisher.kill('SIGINT'); + node.destroy(); + destroy = true; + done(); + } } - }); + ); rclnodejs.spin(node); }); });