diff --git a/editor/js/ui/utils.js b/editor/js/ui/utils.js
index 6d5884cdd..4f84da8ba 100644
--- a/editor/js/ui/utils.js
+++ b/editor/js/ui/utils.js
@@ -34,6 +34,8 @@ RED.utils = (function() {
result = $('').text('buffer['+value.length+']');
} else if (value.hasOwnProperty('type') && value.type === 'array' && value.hasOwnProperty('data')) {
result = $('').text('array['+value.length+']');
+ } else if (value.hasOwnProperty('type') && value.type === 'function') {
+ result = $('').text('function');
} else {
result = $('object');
}
@@ -125,7 +127,7 @@ RED.utils = (function() {
e.stopPropagation();
RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue");
})
- if (strippedKey !== '') {
+ if (strippedKey !== undefined && strippedKey !== '') {
var isPinned = pinnedPaths[sourceId].hasOwnProperty(strippedKey);
var pinPath = $('').appendTo(tools).click(function(e) {
@@ -296,9 +298,12 @@ RED.utils = (function() {
isArray = true;
isArrayObject = true;
}
-
if (obj === null || obj === undefined) {
$(''+obj+'').appendTo(entryObj);
+ } else if (typeHint === "function" || (obj.__encoded__ && obj.type === 'function')) {
+ e = $('').text("function").appendTo(entryObj);
+ } else if (typeHint === "internal" || (obj.__encoded__ && obj.type === 'internal')) {
+ e = $('').text("[internal]").appendTo(entryObj);
} else if (typeof obj === 'string') {
if (/[\t\n\r]/.test(obj)) {
element.addClass('collapsed');
@@ -791,6 +796,29 @@ RED.utils = (function() {
return spinner;
}
+ function decodeObject(payload,format) {
+ if ((format === 'number') && (payload === "NaN")) {
+ payload = Number.NaN;
+ } else if (format === 'Object' || /^array/.test(format) || format === 'boolean' || format === 'number' ) {
+ payload = JSON.parse(payload);
+ } else if (/error/i.test(format)) {
+ payload = JSON.parse(payload);
+ payload = (payload.name?payload.name+": ":"")+payload.message;
+ } else if (format === 'null') {
+ payload = null;
+ } else if (format === 'undefined') {
+ payload = undefined;
+ } else if (/^buffer/.test(format)) {
+ var buffer = payload;
+ payload = [];
+ for (var c = 0; c < buffer.length; c += 2) {
+ payload.push(parseInt(buffer.substr(c, 2), 16));
+ }
+ }
+ return payload;
+ }
+
+
return {
createObjectElement: buildMessageElement,
getMessageProperty: getMessageProperty,
@@ -800,6 +828,7 @@ RED.utils = (function() {
getDefaultNodeIcon: getDefaultNodeIcon,
getNodeIcon: getNodeIcon,
getNodeLabel: getNodeLabel,
- addSpinnerOverlay: addSpinnerOverlay
+ addSpinnerOverlay: addSpinnerOverlay,
+ decodeObject: decodeObject
}
})();
diff --git a/editor/sass/debug.scss b/editor/sass/debug.scss
index aded6d718..a3acd18ff 100644
--- a/editor/sass/debug.scss
+++ b/editor/sass/debug.scss
@@ -64,22 +64,22 @@
display: inline-block;
}
}
- .debug-message-row {
- .debug-message-tools-pin {
- display: none;
- }
- &.debug-message-row-pinned .debug-message-tools-pin {
- display: inline-block;
- }
- &:hover {
- background: #f3f3f3;
- &>.debug-message-tools {
- .debug-message-tools-copy {
- display: inline-block;
- }
- .debug-message-tools-pin {
- display: inline-block;
- }
+}
+.debug-message-row {
+ .debug-message-tools-pin {
+ display: none;
+ }
+ &.debug-message-row-pinned .debug-message-tools-pin {
+ display: inline-block;
+ }
+ &:hover {
+ background: #f3f3f3;
+ &>.debug-message-tools {
+ .debug-message-tools-copy {
+ display: inline-block;
+ }
+ .debug-message-tools-pin {
+ display: inline-block;
}
}
}
diff --git a/nodes/core/core/58-debug.js b/nodes/core/core/58-debug.js
index 3e4290554..fe84d487d 100644
--- a/nodes/core/core/58-debug.js
+++ b/nodes/core/core/58-debug.js
@@ -4,7 +4,6 @@ module.exports = function(RED) {
var util = require("util");
var events = require("events");
var path = require("path");
- var safeJSONStringify = require("json-stringify-safe");
var debuglength = RED.settings.debugMaxLength || 1000;
var useColors = RED.settings.debugUseColors || false;
util.inspect.styles.boolean = "red";
@@ -104,111 +103,7 @@ module.exports = function(RED) {
function sendDebug(msg) {
// don't put blank errors in sidebar (but do add to logs)
//if ((msg.msg === "") && (msg.hasOwnProperty("level")) && (msg.level === 20)) { return; }
- if (msg.msg instanceof Error) {
- msg.format = "error";
- var errorMsg = {};
- if (msg.msg.name) {
- errorMsg.name = msg.msg.name;
- }
- if (msg.msg.hasOwnProperty('message')) {
- errorMsg.message = msg.msg.message;
- } else {
- errorMsg.message = msg.msg.toString();
- }
- msg.msg = JSON.stringify(errorMsg);
- } else if (msg.msg instanceof Buffer) {
- msg.format = "buffer["+msg.msg.length+"]";
- msg.msg = msg.msg.toString('hex');
- if (msg.msg.length > debuglength) {
- msg.msg = msg.msg.substring(0,debuglength);
- }
- } else if (msg.msg && typeof msg.msg === 'object') {
- try {
- msg.format = msg.msg.constructor.name || "Object";
- // Handle special case of msg.req/res objects from HTTP In node
- if (msg.format === "IncomingMessage" || msg.format === "ServerResponse") {
- msg.format = "Object";
- }
- } catch(err) {
- msg.format = "Object";
- }
- if (/error/i.test(msg.format)) {
- msg.msg = JSON.stringify({
- name: msg.msg.name,
- message: msg.msg.message
- });
- } else {
- var isArray = util.isArray(msg.msg);
- if (isArray) {
- msg.format = "array["+msg.msg.length+"]";
- if (msg.msg.length > debuglength) {
- // msg.msg = msg.msg.slice(0,debuglength);
- msg.msg = {
- __encoded__: true,
- type: "array",
- data: msg.msg.slice(0,debuglength),
- length: msg.msg.length
- }
- }
- }
- if (isArray || (msg.format === "Object")) {
- msg.msg = safeJSONStringify(msg.msg, function(key, value) {
- if (key === '_req' || key === '_res') {
- value = "[internal]"
- } else if (value instanceof Error) {
- value = value.toString()
- } else if (util.isArray(value) && value.length > debuglength) {
- value = {
- __encoded__: true,
- type: "array",
- data: value.slice(0,debuglength),
- length: value.length
- }
- } else if (typeof value === 'string') {
- if (value.length > debuglength) {
- value = value.substring(0,debuglength)+"...";
- }
- } else if (value && value.constructor) {
- if (value.type === "Buffer") {
- value.__encoded__ = true;
- value.length = value.data.length;
- if (value.length > debuglength) {
- value.data = value.data.slice(0,debuglength);
- }
- } else if (value.constructor.name === "ServerResponse") {
- value = "[internal]"
- } else if (value.constructor.name === "Socket") {
- value = "[internal]"
- }
- }
- return value;
- }," ");
- } else {
- try { msg.msg = msg.msg.toString(); }
- catch(e) { msg.msg = "[Type not printable]"; }
- }
- }
- } else if (typeof msg.msg === "boolean") {
- msg.format = "boolean";
- msg.msg = msg.msg.toString();
- } else if (typeof msg.msg === "number") {
- msg.format = "number";
- msg.msg = msg.msg.toString();
- } else if (msg.msg === 0) {
- msg.format = "number";
- msg.msg = "0";
- } else if (msg.msg === null || typeof msg.msg === "undefined") {
- msg.format = (msg.msg === null)?"null":"undefined";
- msg.msg = "(undefined)";
- } else {
- msg.format = "string["+msg.msg.length+"]";
- if (msg.msg.length > debuglength) {
- msg.msg = msg.msg.substring(0,debuglength)+"...";
- }
- }
- // if (msg.msg.length > debuglength) {
- // msg.msg = msg.msg.substr(0,debuglength) +" ....";
- // }
+ msg = RED.util.encodeObject(msg,{maxLength:debuglength});
RED.comms.publish("debug",msg);
}
diff --git a/nodes/core/core/lib/debug/debug-utils.js b/nodes/core/core/lib/debug/debug-utils.js
index 17b850327..2d47155ba 100644
--- a/nodes/core/core/lib/debug/debug-utils.js
+++ b/nodes/core/core/lib/debug/debug-utils.js
@@ -455,24 +455,8 @@ RED.debug = (function() {
$(''+name+'').appendTo(metaRow);
}
- if ((format === 'number') && (payload === "NaN")) {
- payload = Number.NaN;
- } else if (format === 'Object' || /^array/.test(format) || format === 'boolean' || format === 'number' ) {
- payload = JSON.parse(payload);
- } else if (/error/i.test(format)) {
- payload = JSON.parse(payload);
- payload = (payload.name?payload.name+": ":"")+payload.message;
- } else if (format === 'null') {
- payload = null;
- } else if (format === 'undefined') {
- payload = undefined;
- } else if (/^buffer/.test(format)) {
- var buffer = payload;
- payload = [];
- for (var c = 0; c < buffer.length; c += 2) {
- payload.push(parseInt(buffer.substr(c, 2), 16));
- }
- }
+ payload = RED.utils.decodeObject(payload,format);
+
var el = $('').appendTo(msg);
var path = o.property||'';
var debugMessage = RED.utils.createObjectElement(payload, {
diff --git a/red/runtime/util.js b/red/runtime/util.js
index 257e87777..022faa65d 100644
--- a/red/runtime/util.js
+++ b/red/runtime/util.js
@@ -16,6 +16,8 @@
var clone = require("clone");
var jsonata = require("jsonata");
+var safeJSONStringify = require("json-stringify-safe");
+var util = require("util");
function generateId() {
return (1+Math.random()*4294967295).toString(16);
@@ -389,7 +391,130 @@ function normaliseNodeTypeName(name) {
return result;
}
+function encodeObject(msg,opts) {
+ var debuglength = 1000;
+ if (opts && opts.hasOwnProperty('maxLength')) {
+ debuglength = opts.maxLength;
+ }
+ var msgType = typeof msg.msg;
+ if (msg.msg instanceof Error) {
+ msg.format = "error";
+ var errorMsg = {};
+ if (msg.msg.name) {
+ errorMsg.name = msg.msg.name;
+ }
+ if (msg.msg.hasOwnProperty('message')) {
+ errorMsg.message = msg.msg.message;
+ } else {
+ errorMsg.message = msg.msg.toString();
+ }
+ msg.msg = JSON.stringify(errorMsg);
+ } else if (msg.msg instanceof Buffer) {
+ msg.format = "buffer["+msg.msg.length+"]";
+ msg.msg = msg.msg.toString('hex');
+ if (msg.msg.length > debuglength) {
+ msg.msg = msg.msg.substring(0,debuglength);
+ }
+ } else if (msg.msg && msgType === 'object') {
+ try {
+ msg.format = msg.msg.constructor.name || "Object";
+ // Handle special case of msg.req/res objects from HTTP In node
+ if (msg.format === "IncomingMessage" || msg.format === "ServerResponse") {
+ msg.format = "Object";
+ }
+ } catch(err) {
+ msg.format = "Object";
+ }
+ if (/error/i.test(msg.format)) {
+ msg.msg = JSON.stringify({
+ name: msg.msg.name,
+ message: msg.msg.message
+ });
+ } else {
+ var isArray = util.isArray(msg.msg);
+ if (isArray) {
+ msg.format = "array["+msg.msg.length+"]";
+ if (msg.msg.length > debuglength) {
+ // msg.msg = msg.msg.slice(0,debuglength);
+ msg.msg = {
+ __encoded__: true,
+ type: "array",
+ data: msg.msg.slice(0,debuglength),
+ length: msg.msg.length
+ }
+ }
+ }
+ if (isArray || (msg.format === "Object")) {
+ msg.msg = safeJSONStringify(msg.msg, function(key, value) {
+ if (key === '_req' || key === '_res') {
+ value = {
+ __encoded__: true,
+ type: "internal"
+ }
+ } else if (value instanceof Error) {
+ value = value.toString()
+ } else if (util.isArray(value) && value.length > debuglength) {
+ value = {
+ __encoded__: true,
+ type: "array",
+ data: value.slice(0,debuglength),
+ length: value.length
+ }
+ } else if (typeof value === 'string') {
+ if (value.length > debuglength) {
+ value = value.substring(0,debuglength)+"...";
+ }
+ } else if (typeof value === 'function') {
+ value = {
+ __encoded__: true,
+ type: "function"
+ }
+ } else if (value && value.constructor) {
+ if (value.type === "Buffer") {
+ value.__encoded__ = true;
+ value.length = value.data.length;
+ if (value.length > debuglength) {
+ value.data = value.data.slice(0,debuglength);
+ }
+ } else if (value.constructor.name === "ServerResponse") {
+ value = "[internal]"
+ } else if (value.constructor.name === "Socket") {
+ value = "[internal]"
+ }
+ }
+ return value;
+ }," ");
+ } else {
+ try { msg.msg = msg.msg.toString(); }
+ catch(e) { msg.msg = "[Type not printable]"; }
+ }
+ }
+ } else if (msgType === "function") {
+ msg.format = "function";
+ msg.msg = "[function]"
+ } else if (msgType === "boolean") {
+ msg.format = "boolean";
+ msg.msg = msg.msg.toString();
+ } else if (msgType === "number") {
+ msg.format = "number";
+ msg.msg = msg.msg.toString();
+ } else if (msg.msg === 0) {
+ msg.format = "number";
+ msg.msg = "0";
+ } else if (msg.msg === null || msgType === "undefined") {
+ msg.format = (msg.msg === null)?"null":"undefined";
+ msg.msg = "(undefined)";
+ } else {
+ msg.format = "string["+msg.msg.length+"]";
+ if (msg.msg.length > debuglength) {
+ msg.msg = msg.msg.substring(0,debuglength)+"...";
+ }
+ }
+ return msg;
+}
+
module.exports = {
+ encodeObject: encodeObject,
ensureString: ensureString,
ensureBuffer: ensureBuffer,
cloneMessage: cloneMessage,