diff --git a/src/lib/monitor-adapter.js b/src/lib/monitor-adapter.js index 7f470ff2e49..bcef430498d 100644 --- a/src/lib/monitor-adapter.js +++ b/src/lib/monitor-adapter.js @@ -2,6 +2,17 @@ import OpcodeLabels from './opcode-labels.js'; const isUndefined = a => typeof a === 'undefined'; +const circularReplacer = () => { + const stack = new Set(); + return function replacer(_, value) { + if (typeof value === "object" && value !== null) { + if (stack.has(value)) return Array.isArray(value) ? "[...]" : "{...}"; + stack.add(value); + } + return value; + }; +}; + /** * Convert monitors from VM format to what the GUI needs to render. * - Convert opcode to a label and a category @@ -32,18 +43,26 @@ export default function ({id, spriteName, opcode, params, value, vm}) { value = Number(value.toFixed(6)); } - // Turn the value to a string, for handle boolean values + // Turn the value to a string, to handle boolean values if (typeof value === 'boolean') { value = value.toString(); } - // Lists can contain booleans, which should also be turned to strings + // Turn the value to a string, to handle JSON values + // do not convert arrays as it will be confused for lists + if (typeof value === 'object' && !Array.isArray(value)) { + value = JSON.stringify(value, circularReplacer()); + } + + // Lists can contain booleans or Objects, which should also be turned to strings if (Array.isArray(value)) { value = value.slice(); for (let i = 0; i < value.length; i++) { const item = value[i]; if (typeof item === 'boolean') { value[i] = item.toString(); + } else if (typeof value[i] === 'object' && !Array.isArray(value[i])) { + value[i] = JSON.stringify(item, circularReplacer()); } } }