feat(shared): support Map and Set in toDisplayString
close #1067, close #1100
This commit is contained in:
		
							parent
							
								
									ff97be15c3
								
							
						
					
					
						commit
						3c60d40827
					
				
							
								
								
									
										107
									
								
								packages/shared/__tests__/toDisplayString.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								packages/shared/__tests__/toDisplayString.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
			
		||||
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
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        }
 | 
			
		||||
      }"
 | 
			
		||||
    `)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
@ -11,6 +11,7 @@ export * from './domTagConfig'
 | 
			
		||||
export * from './domAttrConfig'
 | 
			
		||||
export * from './escapeHtml'
 | 
			
		||||
export * from './looseEqual'
 | 
			
		||||
export * from './toDisplayString'
 | 
			
		||||
 | 
			
		||||
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
 | 
			
		||||
  ? Object.freeze({})
 | 
			
		||||
@ -112,15 +113,6 @@ export const capitalize = cacheStringFunction(
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								packages/shared/src/toDisplayString.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/shared/src/toDisplayString.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user