Skip to content

Commit 2be1dae

Browse files
committed
Use safeStringify() on monitor values like TW/scratch-gui
closes #1021 closes #1022
1 parent 9b866ae commit 2be1dae

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/scaffolding/monitor.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import DropArea from './drop-area';
33
import styles from './style.css';
44
import {readAsText} from '../common/readers';
55
import downloadBlob from './download';
6+
import {safeStringify} from './safe-stringify';
67

78
class Monitor {
89
constructor (parent, monitor) {
@@ -195,9 +196,11 @@ class VariableMonitor extends Monitor {
195196
}
196197

197198
let value = monitor.get('value');
198-
if (typeof value === 'number') {
199+
if (typeof value === 'number' && !Object.is(value, -0)) {
199200
value = Number(value.toFixed(6));
200201
}
202+
value = safeStringify(value);
203+
201204
if (this._value !== value) {
202205
this._value = value;
203206
this.valueElement.textContent = value;
@@ -217,6 +220,7 @@ class Row {
217220
this.monitor = monitor;
218221

219222
this.index = -1;
223+
/** @type {string} Stringified value. */
220224
this.value = '';
221225
this.isFocused = false;
222226

@@ -368,6 +372,8 @@ class Row {
368372
}
369373

370374
setValue (value) {
375+
value = safeStringify(value);
376+
371377
if (this.value !== value && !this.isFocused) {
372378
this.value = value;
373379
if (this.editable) {

src/scaffolding/safe-stringify.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const circularReplacer = () => {
2+
const seen = new WeakSet();
3+
return (_, value) => {
4+
if (typeof value === 'object' && value !== null) {
5+
if (seen.has(value)) {
6+
return Array.isArray(value) ? '[...]' : '{...}';
7+
}
8+
seen.add(value);
9+
}
10+
return value;
11+
};
12+
};
13+
14+
/**
15+
* Safely stringify, properly handling circular relations and -0.
16+
* @param {unknown} input Any value
17+
* @returns {string} A stringified version of the input.
18+
*/
19+
export const safeStringify = input => {
20+
if (typeof input === 'object' && input !== null) {
21+
// TODO: this will not handle -0 inside the input properly, though that is very low priority.
22+
return JSON.stringify(input, circularReplacer());
23+
}
24+
// -0 stringifies as "0" by default.
25+
if (Object.is(input, -0)) {
26+
return '-0';
27+
}
28+
return `${input}`;
29+
};

0 commit comments

Comments
 (0)