--- /dev/null
+import { toDisplayString } from '../src'
+
+describe('toDisplayString', () => {
+ test('nullish values', () => {
+ expect(toDisplayString(null)).toBe('')
+ expect(toDisplayString(undefined)).toBe('')
+ })
+
+ test('primitive values', () => {
+ expect(toDisplayString(1)).toBe('1')
+ expect(toDisplayString(true)).toBe('true')
+ expect(toDisplayString(false)).toBe('false')
+ expect(toDisplayString('hello')).toBe('hello')
+ })
+
+ test('Object and Arrays', () => {
+ const obj = { foo: 123 }
+ expect(toDisplayString(obj)).toBe(JSON.stringify(obj, null, 2))
+ const arr = [obj]
+ expect(toDisplayString(arr)).toBe(JSON.stringify(arr, null, 2))
+ })
+
+ test('native objects', () => {
+ const div = document.createElement('div')
+ expect(toDisplayString(div)).toBe(`"[object HTMLDivElement]"`)
+ expect(toDisplayString({ div })).toMatchInlineSnapshot(`
+ "{
+ \\"div\\": \\"[object HTMLDivElement]\\"
+ }"
+ `)
+ })
+
+ test('Map and Set', () => {
+ const m = new Map<any, any>([
+ [1, 'foo'],
+ [{ baz: 1 }, { foo: 'bar', qux: 2 }]
+ ])
+ const s = new Set<any>([1, { foo: 'bar' }, m])
+
+ expect(toDisplayString(m)).toMatchInlineSnapshot(`
+ "{
+ \\"Map(2)\\": {
+ \\"1 =>\\": \\"foo\\",
+ \\"[object Object] =>\\": {
+ \\"foo\\": \\"bar\\",
+ \\"qux\\": 2
+ }
+ }
+ }"
+ `)
+ expect(toDisplayString(s)).toMatchInlineSnapshot(`
+ "{
+ \\"Set(3)\\": [
+ 1,
+ {
+ \\"foo\\": \\"bar\\"
+ },
+ {
+ \\"Map(2)\\": {
+ \\"1 =>\\": \\"foo\\",
+ \\"[object Object] =>\\": {
+ \\"foo\\": \\"bar\\",
+ \\"qux\\": 2
+ }
+ }
+ }
+ ]
+ }"
+ `)
+
+ expect(
+ toDisplayString({
+ m,
+ s
+ })
+ ).toMatchInlineSnapshot(`
+ "{
+ \\"m\\": {
+ \\"Map(2)\\": {
+ \\"1 =>\\": \\"foo\\",
+ \\"[object Object] =>\\": {
+ \\"foo\\": \\"bar\\",
+ \\"qux\\": 2
+ }
+ }
+ },
+ \\"s\\": {
+ \\"Set(3)\\": [
+ 1,
+ {
+ \\"foo\\": \\"bar\\"
+ },
+ {
+ \\"Map(2)\\": {
+ \\"1 =>\\": \\"foo\\",
+ \\"[object Object] =>\\": {
+ \\"foo\\": \\"bar\\",
+ \\"qux\\": 2
+ }
+ }
+ }
+ ]
+ }
+ }"
+ `)
+ })
+})
export * from './domAttrConfig'
export * from './escapeHtml'
export * from './looseEqual'
+export * from './toDisplayString'
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
? Object.freeze({})
export const hasChanged = (value: any, oldValue: any): boolean =>
value !== oldValue && (value === value || oldValue === oldValue)
-// For converting {{ interpolation }} values to displayed strings.
-export const toDisplayString = (val: unknown): string => {
- return val == null
- ? ''
- : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
- ? JSON.stringify(val, null, 2)
- : String(val)
-}
-
export const invokeArrayFns = (fns: Function[], arg?: any) => {
for (let i = 0; i < fns.length; i++) {
fns[i](arg)
--- /dev/null
+import { isArray, isObject, isPlainObject } from './index'
+
+// For converting {{ interpolation }} values to displayed strings.
+export const toDisplayString = (val: unknown): string => {
+ return val == null
+ ? ''
+ : isObject(val)
+ ? JSON.stringify(val, replacer, 2)
+ : String(val)
+}
+
+const replacer = (_key: string, val: any) => {
+ if (val instanceof Map) {
+ return {
+ [`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => {
+ ;(entries as any)[`${key} =>`] = val
+ return entries
+ }, {})
+ }
+ } else if (val instanceof Set) {
+ return {
+ [`Set(${val.size})`]: [...val.values()]
+ }
+ } else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
+ return String(val)
+ }
+ return val
+}