forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
52 lines
1.4 KiB
52 lines
1.4 KiB
import { isReactive, isReadonly, isRef, toRaw, unref } from "vue"; |
|
|
|
export const CIRCULAR_REFERENCE_TEXT = "[Circular]"; |
|
|
|
export interface CircularReferenceMarker { |
|
__jsonViewCircular: true; |
|
path?: string; |
|
} |
|
|
|
export function createCircularReferenceMarker(path?: string): CircularReferenceMarker { |
|
return { |
|
__jsonViewCircular: true, |
|
path, |
|
}; |
|
} |
|
|
|
export function isCircularReferenceMarker(value: unknown): value is CircularReferenceMarker { |
|
return Boolean( |
|
value && |
|
typeof value === "object" && |
|
"__jsonViewCircular" in value && |
|
(value as { __jsonViewCircular?: boolean }).__jsonViewCircular |
|
); |
|
} |
|
|
|
export function formatCircularReference(path?: string) { |
|
return path ? `[Circular: ${path}]` : CIRCULAR_REFERENCE_TEXT; |
|
} |
|
|
|
export function normalizeVueValue( |
|
value: unknown, |
|
currentPath?: string, |
|
seenRefs = new WeakMap<object, string | undefined>() |
|
): unknown { |
|
let current = value; |
|
|
|
while (isRef(current)) { |
|
const reference = current as object; |
|
const existingPath = seenRefs.get(reference); |
|
if (existingPath !== undefined || seenRefs.has(reference)) { |
|
return createCircularReferenceMarker(existingPath ?? currentPath); |
|
} |
|
seenRefs.set(reference, currentPath); |
|
current = unref(current); |
|
} |
|
|
|
if (current !== null && typeof current === "object" && (isReactive(current) || isReadonly(current))) { |
|
return toRaw(current); |
|
} |
|
|
|
return current; |
|
}
|
|
|