WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit f917195

Browse files
committed
fix: preserve functions in stringifying & parsing
1 parent b953d03 commit f917195

File tree

2 files changed

+32
-28
lines changed

2 files changed

+32
-28
lines changed

frontend/src/components/Code.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { EditorView, keymap } from "@codemirror/view"
3434
import { indentationMarkers } from "@replit/codemirror-indentation-markers"
3535
import { tomorrow } from "thememirror"
3636
import JSON5 from "json5"
37-
import { jsonToJs, isPrivateKey } from "@/utils/helpers"
37+
import { jsonToJs, isPrivateKey, jsonReplacer, jsonReviver } from "@/utils/helpers"
3838
3939
import InputLabel from "@/components/InputLabel.vue"
4040
@@ -72,7 +72,7 @@ const setEditorValue = () => {
7272
let value = props.modelValue ?? ""
7373
try {
7474
if (props.language === "json" || typeof value === "object") {
75-
value = JSON5.stringify(value, { replacer: null, space: 2, quote: '"' })
75+
value = JSON5.stringify(value, { replacer: jsonReplacer, space: 2, quote: '"' })
7676
}
7777
code.value = value
7878
} catch (e) {
@@ -103,7 +103,7 @@ const emitEditorValue = () => {
103103
} else if (props.language === "javascript" && isValidObjectString(value)) {
104104
try {
105105
// forgiving single-quoted/unquoted keys; trailing commas
106-
value = JSON5.parse(value)
106+
value = JSON5.parse(value, jsonReviver)
107107
} catch (e) {
108108
// fallback to JSON parsing
109109
value = jsonToJs(value)

frontend/src/utils/helpers.ts

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -239,38 +239,40 @@ function isJSONString(str: string) {
239239
return true
240240
}
241241

242-
function jsToJson(obj: ObjectLiteral): string {
243-
const replacer = (_key: string, value: any) => {
244-
// Preserve functions by converting them to strings
245-
if (typeof value === "function") {
246-
return value.toString()
242+
const jsonReplacer = (_key: string, value: any) => {
243+
// Preserve functions by converting them to strings
244+
if (typeof value === "function") {
245+
return value.toString()
246+
}
247+
// Handle circular references
248+
if (typeof value === "object" && value !== null) {
249+
if (value instanceof Set) {
250+
return [...value]
247251
}
248-
// Handle circular references
249-
if (typeof value === "object" && value !== null) {
250-
if (value instanceof Set) {
251-
return [...value]
252-
}
253-
if (value instanceof Map) {
254-
return Object.fromEntries(value.entries())
255-
}
252+
if (value instanceof Map) {
253+
return Object.fromEntries(value.entries())
256254
}
257-
return value
258255
}
259-
return JSON.stringify(obj, replacer, 2)
256+
return value
260257
}
261258

262-
function jsonToJs(json: string): any {
259+
function jsToJson(obj: ObjectLiteral): string {
260+
return JSON.stringify(obj, jsonReplacer, 2)
261+
}
262+
263+
const jsonReviver = (_key: string, value: any) => {
263264
const registeredComponents = window.__APP_COMPONENTS__ || {}
264-
const reviver = (_key: string, value: any) => {
265-
// Convert functions back to functions
266-
if (typeof value === "string" && value.startsWith("function")) {
267-
// provide access to render function & frappeUI lib for editing props
268-
const newFunc = new Function("scope", `with(scope) { return ${value}; }`)
269-
return newFunc({"h": h, ...registeredComponents})
270-
}
271-
return value
265+
// Convert functions back to functions
266+
if (typeof value === "string" && value.startsWith("function")) {
267+
// provide access to render function & frappeUI lib for editing props
268+
const newFunc = new Function("scope", `with(scope) { return ${value}; }`)
269+
return newFunc({"h": h, ...registeredComponents})
272270
}
273-
return JSON.parse(json, reviver)
271+
return value
272+
}
273+
274+
function jsonToJs(json: string): any {
275+
return JSON.parse(json, jsonReviver)
274276
}
275277

276278
const mapToObject = (map: Map<any, any>) => Object.fromEntries(map.entries());
@@ -584,6 +586,8 @@ export {
584586
isJSONString,
585587
jsToJson,
586588
jsonToJs,
589+
jsonReplacer,
590+
jsonReviver,
587591
mapToObject,
588592
replaceMapKey,
589593
isTargetEditable,

0 commit comments

Comments
 (0)