Skip to content

Commit 3c60d40

Browse files
committed
feat(shared): support Map and Set in toDisplayString
close #1067, close #1100
1 parent ff97be1 commit 3c60d40

File tree

3 files changed

+136
-9
lines changed

3 files changed

+136
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { toDisplayString } from '../src'
2+
3+
describe('toDisplayString', () => {
4+
test('nullish values', () => {
5+
expect(toDisplayString(null)).toBe('')
6+
expect(toDisplayString(undefined)).toBe('')
7+
})
8+
9+
test('primitive values', () => {
10+
expect(toDisplayString(1)).toBe('1')
11+
expect(toDisplayString(true)).toBe('true')
12+
expect(toDisplayString(false)).toBe('false')
13+
expect(toDisplayString('hello')).toBe('hello')
14+
})
15+
16+
test('Object and Arrays', () => {
17+
const obj = { foo: 123 }
18+
expect(toDisplayString(obj)).toBe(JSON.stringify(obj, null, 2))
19+
const arr = [obj]
20+
expect(toDisplayString(arr)).toBe(JSON.stringify(arr, null, 2))
21+
})
22+
23+
test('native objects', () => {
24+
const div = document.createElement('div')
25+
expect(toDisplayString(div)).toBe(`"[object HTMLDivElement]"`)
26+
expect(toDisplayString({ div })).toMatchInlineSnapshot(`
27+
"{
28+
\\"div\\": \\"[object HTMLDivElement]\\"
29+
}"
30+
`)
31+
})
32+
33+
test('Map and Set', () => {
34+
const m = new Map<any, any>([
35+
[1, 'foo'],
36+
[{ baz: 1 }, { foo: 'bar', qux: 2 }]
37+
])
38+
const s = new Set<any>([1, { foo: 'bar' }, m])
39+
40+
expect(toDisplayString(m)).toMatchInlineSnapshot(`
41+
"{
42+
\\"Map(2)\\": {
43+
\\"1 =>\\": \\"foo\\",
44+
\\"[object Object] =>\\": {
45+
\\"foo\\": \\"bar\\",
46+
\\"qux\\": 2
47+
}
48+
}
49+
}"
50+
`)
51+
expect(toDisplayString(s)).toMatchInlineSnapshot(`
52+
"{
53+
\\"Set(3)\\": [
54+
1,
55+
{
56+
\\"foo\\": \\"bar\\"
57+
},
58+
{
59+
\\"Map(2)\\": {
60+
\\"1 =>\\": \\"foo\\",
61+
\\"[object Object] =>\\": {
62+
\\"foo\\": \\"bar\\",
63+
\\"qux\\": 2
64+
}
65+
}
66+
}
67+
]
68+
}"
69+
`)
70+
71+
expect(
72+
toDisplayString({
73+
m,
74+
s
75+
})
76+
).toMatchInlineSnapshot(`
77+
"{
78+
\\"m\\": {
79+
\\"Map(2)\\": {
80+
\\"1 =>\\": \\"foo\\",
81+
\\"[object Object] =>\\": {
82+
\\"foo\\": \\"bar\\",
83+
\\"qux\\": 2
84+
}
85+
}
86+
},
87+
\\"s\\": {
88+
\\"Set(3)\\": [
89+
1,
90+
{
91+
\\"foo\\": \\"bar\\"
92+
},
93+
{
94+
\\"Map(2)\\": {
95+
\\"1 =>\\": \\"foo\\",
96+
\\"[object Object] =>\\": {
97+
\\"foo\\": \\"bar\\",
98+
\\"qux\\": 2
99+
}
100+
}
101+
}
102+
]
103+
}
104+
}"
105+
`)
106+
})
107+
})

packages/shared/src/index.ts

+1-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './domTagConfig'
1111
export * from './domAttrConfig'
1212
export * from './escapeHtml'
1313
export * from './looseEqual'
14+
export * from './toDisplayString'
1415

1516
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
1617
? Object.freeze({})
@@ -112,15 +113,6 @@ export const capitalize = cacheStringFunction(
112113
export const hasChanged = (value: any, oldValue: any): boolean =>
113114
value !== oldValue && (value === value || oldValue === oldValue)
114115

115-
// For converting {{ interpolation }} values to displayed strings.
116-
export const toDisplayString = (val: unknown): string => {
117-
return val == null
118-
? ''
119-
: isArray(val) || (isPlainObject(val) && val.toString === objectToString)
120-
? JSON.stringify(val, null, 2)
121-
: String(val)
122-
}
123-
124116
export const invokeArrayFns = (fns: Function[], arg?: any) => {
125117
for (let i = 0; i < fns.length; i++) {
126118
fns[i](arg)
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { isArray, isObject, isPlainObject } from './index'
2+
3+
// For converting {{ interpolation }} values to displayed strings.
4+
export const toDisplayString = (val: unknown): string => {
5+
return val == null
6+
? ''
7+
: isObject(val)
8+
? JSON.stringify(val, replacer, 2)
9+
: String(val)
10+
}
11+
12+
const replacer = (_key: string, val: any) => {
13+
if (val instanceof Map) {
14+
return {
15+
[`Map(${val.size})`]: [...val.entries()].reduce((entries, [key, val]) => {
16+
;(entries as any)[`${key} =>`] = val
17+
return entries
18+
}, {})
19+
}
20+
} else if (val instanceof Set) {
21+
return {
22+
[`Set(${val.size})`]: [...val.values()]
23+
}
24+
} else if (isObject(val) && !isArray(val) && !isPlainObject(val)) {
25+
return String(val)
26+
}
27+
return val
28+
}

0 commit comments

Comments
 (0)