@node-red/util 5.0.7 → 5.0.9

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 (2) hide show
  1. package/lib/util.js +71 -3
  2. package/package.json +3 -3
package/lib/util.js CHANGED
@@ -171,6 +171,15 @@ function compareObjects(obj1,obj2) {
171
171
  }
172
172
  }
173
173
 
174
+ var isDate1 = obj1 instanceof Date;
175
+ var isDate2 = obj2 instanceof Date;
176
+ if (isDate1 != isDate2) {
177
+ return false;
178
+ }
179
+ if (isDate1 && isDate2) {
180
+ return obj1.getTime() === obj2.getTime();
181
+ }
182
+
174
183
  if (typeof obj1 !== 'object' || typeof obj2 !== 'object') {
175
184
  return false;
176
185
  }
@@ -470,6 +479,10 @@ function setObjectProperty(msg,prop,value,createMissing) {
470
479
  var obj = msg;
471
480
  var key;
472
481
  for (var i=0;i<length-1;i++) {
482
+ if (obj === null || (typeof obj !== "object" && typeof obj !== "function")) {
483
+ // Cannot traverse a property beneath a non-object/array
484
+ return false;
485
+ }
473
486
  key = msgPropParts[i];
474
487
  if (typeof key === 'string' || (typeof key === 'number' && !Array.isArray(obj))) {
475
488
  if (Object.hasOwn(obj, key)) {
@@ -507,6 +520,10 @@ function setObjectProperty(msg,prop,value,createMissing) {
507
520
  }
508
521
  }
509
522
  }
523
+ if (obj === null || (typeof obj !== "object" && typeof obj !== "function")) {
524
+ // Cannot set or delete a property beneath a non-object/array
525
+ return false;
526
+ }
510
527
  key = msgPropParts[length-1];
511
528
  if (typeof value === "undefined") {
512
529
  if (typeof key === 'number' && Array.isArray(obj)) {
@@ -858,6 +875,56 @@ function normaliseNodeTypeName(name) {
858
875
  return result;
859
876
  }
860
877
 
878
+ /**
879
+ * Full length of a Buffer whose toJSON data was truncated by
880
+ * stringifyWithTruncatedBuffers
881
+ */
882
+ const truncatedBufferLength = Symbol("truncatedBufferLength");
883
+
884
+ /**
885
+ * Stringify an object like safeJSONStringify, but only convert the first
886
+ * `maxLength` bytes of any Buffer that is longer than that.
887
+ *
888
+ * JSON.stringify calls Buffer's toJSON, which copies every byte into an
889
+ * array, before the replacer gets to see the value. For large Buffers that
890
+ * can take a long time or exhaust the heap, so a truncating toJSON is used
891
+ * for the duration of the call.
892
+ * @param {Object} obj - the object to stringify
893
+ * @param {Number} maxLength - the number of bytes to keep of each Buffer
894
+ * @param {Function} replacer - the replacer for safeJSONStringify
895
+ * @return {String} the JSON string
896
+ */
897
+ function stringifyWithTruncatedBuffers(obj, maxLength, replacer) {
898
+ if (!(maxLength >= 0)) {
899
+ return safeJSONStringify(obj, replacer);
900
+ }
901
+ const bufferToJSON = Buffer.prototype.toJSON;
902
+ const truncatingToJSON = function() {
903
+ if (this.length <= maxLength) {
904
+ return bufferToJSON.call(this);
905
+ }
906
+ const value = {
907
+ type: "Buffer",
908
+ data: Array.from(this.subarray(0,maxLength))
909
+ };
910
+ value[truncatedBufferLength] = this.length;
911
+ return value;
912
+ };
913
+ Buffer.prototype.toJSON = truncatingToJSON;
914
+ // The finally block is skipped if execution is terminated while
915
+ // stringifying, e.g. by the timeout of a Function node calling node.warn
916
+ process.nextTick(function() {
917
+ if (Buffer.prototype.toJSON === truncatingToJSON) {
918
+ Buffer.prototype.toJSON = bufferToJSON;
919
+ }
920
+ });
921
+ try {
922
+ return safeJSONStringify(obj, replacer);
923
+ } finally {
924
+ Buffer.prototype.toJSON = bufferToJSON;
925
+ }
926
+ }
927
+
861
928
  /**
862
929
  * Encode an object to JSON without losing information about non-JSON types
863
930
  * such as Buffer and Function.
@@ -903,7 +970,8 @@ function encodeObject(msg,opts) {
903
970
  msg.msg = JSON.stringify(value);
904
971
  } else if (msg.msg instanceof Buffer) {
905
972
  msg.format = "buffer["+msg.msg.length+"]";
906
- msg.msg = msg.msg.toString('hex');
973
+ // Only hex encode the bytes that will be shown
974
+ msg.msg = msg.msg.toString('hex', 0, debuglength >= 0 ? Math.ceil(debuglength/2) : undefined);
907
975
  if (msg.msg.length > debuglength) {
908
976
  msg.msg = msg.msg.substring(0,debuglength);
909
977
  }
@@ -962,7 +1030,7 @@ function encodeObject(msg,opts) {
962
1030
  msg.msg = msg.msg.toString();
963
1031
  }
964
1032
  if (needsStringify || (msg.format === "Object")) {
965
- msg.msg = safeJSONStringify(msg.msg, function(key, value) {
1033
+ msg.msg = stringifyWithTruncatedBuffers(msg.msg, debuglength, function(key, value) {
966
1034
  if (key === '_req' || key === '_res') {
967
1035
  value = {
968
1036
  __enc__: true,
@@ -1034,7 +1102,7 @@ function encodeObject(msg,opts) {
1034
1102
  } else if (value && value.constructor) {
1035
1103
  if (value.type === "Buffer") {
1036
1104
  value.__enc__ = true;
1037
- value.length = value.data.length;
1105
+ value.length = value[truncatedBufferLength] ?? value.data.length;
1038
1106
  if (value.length > debuglength) {
1039
1107
  value.data = value.data.slice(0,debuglength);
1040
1108
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/util",
3
- "version": "5.0.7",
3
+ "version": "5.0.9",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,11 +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
22
  "lodash.clonedeep": "^4.5.0",
23
- "moment": "2.30.1",
23
+ "moment": "2.31.0",
24
24
  "moment-timezone": "0.5.48"
25
25
  }
26
26
  }