@node-red/util 5.0.3 → 5.0.5
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.
- package/lib/util.js +55 -9
- package/package.json +2 -2
package/lib/util.js
CHANGED
|
@@ -24,7 +24,6 @@ const jsonata = require("jsonata");
|
|
|
24
24
|
const moment = require("moment-timezone");
|
|
25
25
|
const safeJSONStringify = require("json-stringify-safe");
|
|
26
26
|
const util = require("util");
|
|
27
|
-
const { hasOwnProperty } = Object.prototype;
|
|
28
27
|
const log = require("./log")
|
|
29
28
|
/**
|
|
30
29
|
* Safely returns the object constructor name.
|
|
@@ -182,7 +181,7 @@ function compareObjects(obj1,obj2) {
|
|
|
182
181
|
}
|
|
183
182
|
for (var k in obj1) {
|
|
184
183
|
/* istanbul ignore else */
|
|
185
|
-
if (
|
|
184
|
+
if (Object.hasOwn(obj1, k)) {
|
|
186
185
|
if (!compareObjects(obj1[k],obj2[k])) {
|
|
187
186
|
return false;
|
|
188
187
|
}
|
|
@@ -473,7 +472,7 @@ function setObjectProperty(msg,prop,value,createMissing) {
|
|
|
473
472
|
for (var i=0;i<length-1;i++) {
|
|
474
473
|
key = msgPropParts[i];
|
|
475
474
|
if (typeof key === 'string' || (typeof key === 'number' && !Array.isArray(obj))) {
|
|
476
|
-
if (
|
|
475
|
+
if (Object.hasOwn(obj, key)) {
|
|
477
476
|
if (length > 1 && ((typeof obj[key] !== "object" && typeof obj[key] !== "function") || obj[key] === null)) {
|
|
478
477
|
// Break out early as we cannot create a property beneath
|
|
479
478
|
// this type of value
|
|
@@ -570,7 +569,7 @@ function getSetting(node, name, flow_) {
|
|
|
570
569
|
* @memberof @node-red/util_util
|
|
571
570
|
*/
|
|
572
571
|
function evaluateEnvProperty(value, node) {
|
|
573
|
-
var flow = (node &&
|
|
572
|
+
var flow = (node && Object.hasOwn(node, "_flow")) ? node._flow : null;
|
|
574
573
|
var result;
|
|
575
574
|
if (/^\${[^}]+}$/.test(value)) {
|
|
576
575
|
// ${ENV_VAR}
|
|
@@ -782,12 +781,59 @@ function evaluateJSONataExpression(expr,msg,callback) {
|
|
|
782
781
|
}
|
|
783
782
|
|
|
784
783
|
expr.evaluate(context, bindings).then(result => {
|
|
785
|
-
callback(null, result)
|
|
784
|
+
callback(null, normaliseJSONataResult(result, new WeakSet()))
|
|
786
785
|
}).catch(err => {
|
|
787
786
|
callback(err)
|
|
788
787
|
})
|
|
789
788
|
}
|
|
790
789
|
|
|
790
|
+
/**
|
|
791
|
+
* Restore the standard Object prototype on any object created by JSONata.
|
|
792
|
+
*
|
|
793
|
+
* JSONata 2.2.1 hardened itself against prototype pollution by building its
|
|
794
|
+
* internal objects with `Object.create(null)`. Those objects surface in the
|
|
795
|
+
* expression result, so anything downstream calling `obj.hasOwnProperty(...)` -
|
|
796
|
+
* or relying on `toString` - will throw. We cannot assume code outside our
|
|
797
|
+
* control avoids that, so the prototype is restored before the result is
|
|
798
|
+
* handed back.
|
|
799
|
+
*
|
|
800
|
+
* The result must be walked, not just checked at the top level: JSONata leaves
|
|
801
|
+
* null-prototype objects nested inside plain objects and, commonly, as the
|
|
802
|
+
* members of a returned array (`items.{...}`, `$map(...)`, `$append(...)`).
|
|
803
|
+
*
|
|
804
|
+
* Only plain objects and arrays are traversed. Buffers, Dates and class
|
|
805
|
+
* instances are passed through untouched: JSONata never places a constructed
|
|
806
|
+
* object inside one, and walking them would be expensive (a Buffer has one own
|
|
807
|
+
* key per byte) and unsafe (property getters on msg.req/msg.res may have side
|
|
808
|
+
* effects).
|
|
809
|
+
*
|
|
810
|
+
* @param {any} value - the JSONata result to normalise, modified in place
|
|
811
|
+
* @param {WeakSet} seen - objects already visited, to survive circular references
|
|
812
|
+
* @return {any} the value that was passed in
|
|
813
|
+
*/
|
|
814
|
+
function normaliseJSONataResult(value, seen) {
|
|
815
|
+
if (value === null || typeof value !== 'object') { return value }
|
|
816
|
+
if (seen.has(value)) { return value }
|
|
817
|
+
seen.add(value)
|
|
818
|
+
if (Array.isArray(value)) {
|
|
819
|
+
for (var i = 0; i < value.length; i++) {
|
|
820
|
+
normaliseJSONataResult(value[i], seen)
|
|
821
|
+
}
|
|
822
|
+
return value
|
|
823
|
+
}
|
|
824
|
+
var proto = Object.getPrototypeOf(value)
|
|
825
|
+
if (proto === null) {
|
|
826
|
+
Object.setPrototypeOf(value, Object.prototype)
|
|
827
|
+
} else if (proto !== Object.prototype) {
|
|
828
|
+
return value
|
|
829
|
+
}
|
|
830
|
+
var keys = Object.keys(value)
|
|
831
|
+
for (var k = 0; k < keys.length; k++) {
|
|
832
|
+
normaliseJSONataResult(value[keys[k]], seen)
|
|
833
|
+
}
|
|
834
|
+
return value
|
|
835
|
+
}
|
|
836
|
+
|
|
791
837
|
/**
|
|
792
838
|
* Normalise a node type name to camel case.
|
|
793
839
|
*
|
|
@@ -824,7 +870,7 @@ function normaliseNodeTypeName(name) {
|
|
|
824
870
|
function encodeObject(msg,opts) {
|
|
825
871
|
try {
|
|
826
872
|
var debuglength = 1000;
|
|
827
|
-
if (opts &&
|
|
873
|
+
if (opts && Object.hasOwn(opts, 'maxLength')) {
|
|
828
874
|
debuglength = opts.maxLength;
|
|
829
875
|
}
|
|
830
876
|
var msgType = typeof msg.msg;
|
|
@@ -837,7 +883,7 @@ function encodeObject(msg,opts) {
|
|
|
837
883
|
type: 'error',
|
|
838
884
|
data: {
|
|
839
885
|
name: msg.msg.name,
|
|
840
|
-
message:
|
|
886
|
+
message: Object.hasOwn(msg.msg, 'message') ? msg.msg.message : msg.msg.toString(),
|
|
841
887
|
code: msg.msg.code,
|
|
842
888
|
cause: cause + "",
|
|
843
889
|
stack: msg.msg.stack,
|
|
@@ -928,7 +974,7 @@ function encodeObject(msg,opts) {
|
|
|
928
974
|
type: 'error',
|
|
929
975
|
data: {
|
|
930
976
|
name: value.name,
|
|
931
|
-
message:
|
|
977
|
+
message: Object.hasOwn(value, 'message') ? value.message : value.toString(),
|
|
932
978
|
code,
|
|
933
979
|
cause: cause + "",
|
|
934
980
|
stack: value.stack,
|
|
@@ -1079,7 +1125,7 @@ function encodeObject(msg,opts) {
|
|
|
1079
1125
|
type: 'error',
|
|
1080
1126
|
data: {
|
|
1081
1127
|
name: e.name,
|
|
1082
|
-
message: 'encodeObject Error: ' + (
|
|
1128
|
+
message: 'encodeObject Error: ' + (Object.hasOwn(e, 'message') ? e.message : e.toString()),
|
|
1083
1129
|
stack: e.stack,
|
|
1084
1130
|
}
|
|
1085
1131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-red/util",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"fs-extra": "11.4.0",
|
|
20
20
|
"i18next": "25.8.14",
|
|
21
21
|
"json-stringify-safe": "5.0.1",
|
|
22
|
-
"jsonata": "2.2.
|
|
22
|
+
"jsonata": "2.2.2",
|
|
23
23
|
"lodash.clonedeep": "^4.5.0",
|
|
24
24
|
"moment": "2.30.1",
|
|
25
25
|
"moment-timezone": "0.5.48"
|