@node-red/util 5.0.6 → 5.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/jsonata.js +7699 -0
  2. package/lib/util.js +66 -5
  3. package/package.json +3 -4
package/lib/util.js CHANGED
@@ -20,11 +20,11 @@
20
20
  */
21
21
 
22
22
  const clonedeep = require("lodash.clonedeep");
23
- const jsonata = require("jsonata");
24
23
  const moment = require("moment-timezone");
25
24
  const safeJSONStringify = require("json-stringify-safe");
26
25
  const util = require("util");
27
26
  const log = require("./log")
27
+ const jsonata = require("./jsonata");
28
28
  /**
29
29
  * Safely returns the object constructor name.
30
30
  * @return {String} the name of the object constructor if it exists, empty string otherwise.
@@ -470,6 +470,10 @@ function setObjectProperty(msg,prop,value,createMissing) {
470
470
  var obj = msg;
471
471
  var key;
472
472
  for (var i=0;i<length-1;i++) {
473
+ if (obj === null || (typeof obj !== "object" && typeof obj !== "function")) {
474
+ // Cannot traverse a property beneath a non-object/array
475
+ return false;
476
+ }
473
477
  key = msgPropParts[i];
474
478
  if (typeof key === 'string' || (typeof key === 'number' && !Array.isArray(obj))) {
475
479
  if (Object.hasOwn(obj, key)) {
@@ -507,6 +511,10 @@ function setObjectProperty(msg,prop,value,createMissing) {
507
511
  }
508
512
  }
509
513
  }
514
+ if (obj === null || (typeof obj !== "object" && typeof obj !== "function")) {
515
+ // Cannot set or delete a property beneath a non-object/array
516
+ return false;
517
+ }
510
518
  key = msgPropParts[length-1];
511
519
  if (typeof value === "undefined") {
512
520
  if (typeof key === 'number' && Array.isArray(obj)) {
@@ -724,7 +732,9 @@ function prepareJSONataExpression(value,node) {
724
732
  }
725
733
  });
726
734
  expr.assign('moment', function(arg1, arg2, arg3, arg4) {
727
- return moment(arg1, arg2, arg3, arg4);
735
+ const result = moment(arg1, arg2, arg3, arg4);
736
+ return result;
737
+ // return moment(arg1, arg2, arg3, arg4);
728
738
  });
729
739
  expr.registerFunction('clone', cloneMessage, '<(oa)-:o>');
730
740
  expr._legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(value);
@@ -856,6 +866,56 @@ function normaliseNodeTypeName(name) {
856
866
  return result;
857
867
  }
858
868
 
869
+ /**
870
+ * Full length of a Buffer whose toJSON data was truncated by
871
+ * stringifyWithTruncatedBuffers
872
+ */
873
+ const truncatedBufferLength = Symbol("truncatedBufferLength");
874
+
875
+ /**
876
+ * Stringify an object like safeJSONStringify, but only convert the first
877
+ * `maxLength` bytes of any Buffer that is longer than that.
878
+ *
879
+ * JSON.stringify calls Buffer's toJSON, which copies every byte into an
880
+ * array, before the replacer gets to see the value. For large Buffers that
881
+ * can take a long time or exhaust the heap, so a truncating toJSON is used
882
+ * for the duration of the call.
883
+ * @param {Object} obj - the object to stringify
884
+ * @param {Number} maxLength - the number of bytes to keep of each Buffer
885
+ * @param {Function} replacer - the replacer for safeJSONStringify
886
+ * @return {String} the JSON string
887
+ */
888
+ function stringifyWithTruncatedBuffers(obj, maxLength, replacer) {
889
+ if (!(maxLength >= 0)) {
890
+ return safeJSONStringify(obj, replacer);
891
+ }
892
+ const bufferToJSON = Buffer.prototype.toJSON;
893
+ const truncatingToJSON = function() {
894
+ if (this.length <= maxLength) {
895
+ return bufferToJSON.call(this);
896
+ }
897
+ const value = {
898
+ type: "Buffer",
899
+ data: Array.from(this.subarray(0,maxLength))
900
+ };
901
+ value[truncatedBufferLength] = this.length;
902
+ return value;
903
+ };
904
+ Buffer.prototype.toJSON = truncatingToJSON;
905
+ // The finally block is skipped if execution is terminated while
906
+ // stringifying, e.g. by the timeout of a Function node calling node.warn
907
+ process.nextTick(function() {
908
+ if (Buffer.prototype.toJSON === truncatingToJSON) {
909
+ Buffer.prototype.toJSON = bufferToJSON;
910
+ }
911
+ });
912
+ try {
913
+ return safeJSONStringify(obj, replacer);
914
+ } finally {
915
+ Buffer.prototype.toJSON = bufferToJSON;
916
+ }
917
+ }
918
+
859
919
  /**
860
920
  * Encode an object to JSON without losing information about non-JSON types
861
921
  * such as Buffer and Function.
@@ -901,7 +961,8 @@ function encodeObject(msg,opts) {
901
961
  msg.msg = JSON.stringify(value);
902
962
  } else if (msg.msg instanceof Buffer) {
903
963
  msg.format = "buffer["+msg.msg.length+"]";
904
- msg.msg = msg.msg.toString('hex');
964
+ // Only hex encode the bytes that will be shown
965
+ msg.msg = msg.msg.toString('hex', 0, debuglength >= 0 ? Math.ceil(debuglength/2) : undefined);
905
966
  if (msg.msg.length > debuglength) {
906
967
  msg.msg = msg.msg.substring(0,debuglength);
907
968
  }
@@ -960,7 +1021,7 @@ function encodeObject(msg,opts) {
960
1021
  msg.msg = msg.msg.toString();
961
1022
  }
962
1023
  if (needsStringify || (msg.format === "Object")) {
963
- msg.msg = safeJSONStringify(msg.msg, function(key, value) {
1024
+ msg.msg = stringifyWithTruncatedBuffers(msg.msg, debuglength, function(key, value) {
964
1025
  if (key === '_req' || key === '_res') {
965
1026
  value = {
966
1027
  __enc__: true,
@@ -1032,7 +1093,7 @@ function encodeObject(msg,opts) {
1032
1093
  } else if (value && value.constructor) {
1033
1094
  if (value.type === "Buffer") {
1034
1095
  value.__enc__ = true;
1035
- value.length = value.data.length;
1096
+ value.length = value[truncatedBufferLength] ?? value.data.length;
1036
1097
  if (value.length > debuglength) {
1037
1098
  value.data = value.data.slice(0,debuglength);
1038
1099
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/util",
3
- "version": "5.0.6",
3
+ "version": "5.0.8",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,12 +16,11 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "chalk": "^4.1.2",
19
- "fs-extra": "11.4.0",
19
+ "fs-extra": "11.4.1",
20
20
  "i18next": "25.8.14",
21
21
  "json-stringify-safe": "5.0.1",
22
- "jsonata": "2.2.2",
23
22
  "lodash.clonedeep": "^4.5.0",
24
- "moment": "2.30.1",
23
+ "moment": "2.31.0",
25
24
  "moment-timezone": "0.5.48"
26
25
  }
27
26
  }