@@ -22,17 +22,32 @@ const object_proto_names = Object.getOwnPropertyNames(Object.prototype)
22
22
. sort ( )
23
23
. join ( '\0' ) ;
24
24
25
+ class DevalueError extends Error {
26
+ /**
27
+ * @param {string } message
28
+ * @param {string[] } keys
29
+ */
30
+ constructor ( message , keys ) {
31
+ super ( message ) ;
32
+ this . name = 'DevalueError' ;
33
+ this . path = keys . join ( '' ) ;
34
+ }
35
+ }
36
+
25
37
/**
26
38
* Turn a value into the JavaScript that creates an equivalent value
27
39
* @param {any } value
28
40
*/
29
41
export function devalue ( value ) {
30
42
const counts = new Map ( ) ;
31
43
44
+ /** @type {string[] } */
45
+ const keys = [ ] ;
46
+
32
47
/** @param {any } thing */
33
48
function walk ( thing ) {
34
49
if ( typeof thing === 'function' ) {
35
- throw new Error ( `Cannot stringify a function` ) ;
50
+ throw new DevalueError ( `Cannot stringify a function` , keys ) ;
36
51
}
37
52
38
53
if ( counts . has ( thing ) ) {
@@ -55,14 +70,27 @@ export function devalue(value) {
55
70
return ;
56
71
57
72
case 'Array' :
58
- thing . forEach ( walk ) ;
73
+ /** @type {any[] } */ ( thing ) . forEach ( ( value , i ) => {
74
+ keys . push ( `[${ i } ]` ) ;
75
+ walk ( value ) ;
76
+ keys . pop ( ) ;
77
+ } ) ;
59
78
break ;
60
79
61
80
case 'Set' :
62
- case 'Map' :
63
81
Array . from ( thing ) . forEach ( walk ) ;
64
82
break ;
65
83
84
+ case 'Map' :
85
+ for ( const [ key , value ] of thing ) {
86
+ keys . push (
87
+ `.get(${ is_primitive ( key ) ? stringify_primitive ( key ) : '...' } )`
88
+ ) ;
89
+ walk ( value ) ;
90
+ keys . pop ( ) ;
91
+ }
92
+ break ;
93
+
66
94
default :
67
95
const proto = Object . getPrototypeOf ( thing ) ;
68
96
@@ -72,14 +100,24 @@ export function devalue(value) {
72
100
Object . getOwnPropertyNames ( proto ) . sort ( ) . join ( '\0' ) !==
73
101
object_proto_names
74
102
) {
75
- throw new Error ( `Cannot stringify arbitrary non-POJOs` ) ;
103
+ throw new DevalueError (
104
+ `Cannot stringify arbitrary non-POJOs` ,
105
+ keys
106
+ ) ;
76
107
}
77
108
78
109
if ( Object . getOwnPropertySymbols ( thing ) . length > 0 ) {
79
- throw new Error ( `Cannot stringify POJOs with symbolic keys` ) ;
110
+ throw new DevalueError (
111
+ `Cannot stringify POJOs with symbolic keys` ,
112
+ keys
113
+ ) ;
80
114
}
81
115
82
- Object . keys ( thing ) . forEach ( ( key ) => walk ( thing [ key ] ) ) ;
116
+ for ( const key in thing ) {
117
+ keys . push ( `.${ key } ` ) ;
118
+ walk ( thing [ key ] ) ;
119
+ keys . pop ( ) ;
120
+ }
83
121
}
84
122
}
85
123
}
0 commit comments