@@ -22,17 +22,32 @@ const object_proto_names = Object.getOwnPropertyNames(Object.prototype)
2222 . sort ( )
2323 . join ( '\0' ) ;
2424
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+
2537/**
2638 * Turn a value into the JavaScript that creates an equivalent value
2739 * @param {any } value
2840 */
2941export function devalue ( value ) {
3042 const counts = new Map ( ) ;
3143
44+ /** @type {string[] } */
45+ const keys = [ ] ;
46+
3247 /** @param {any } thing */
3348 function walk ( thing ) {
3449 if ( typeof thing === 'function' ) {
35- throw new Error ( `Cannot stringify a function` ) ;
50+ throw new DevalueError ( `Cannot stringify a function` , keys ) ;
3651 }
3752
3853 if ( counts . has ( thing ) ) {
@@ -55,14 +70,27 @@ export function devalue(value) {
5570 return ;
5671
5772 case 'Array' :
58- thing . forEach ( walk ) ;
73+ /** @type {any[] } */ ( thing ) . forEach ( ( value , i ) => {
74+ keys . push ( `[${ i } ]` ) ;
75+ walk ( value ) ;
76+ keys . pop ( ) ;
77+ } ) ;
5978 break ;
6079
6180 case 'Set' :
62- case 'Map' :
6381 Array . from ( thing ) . forEach ( walk ) ;
6482 break ;
6583
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+
6694 default :
6795 const proto = Object . getPrototypeOf ( thing ) ;
6896
@@ -72,14 +100,24 @@ export function devalue(value) {
72100 Object . getOwnPropertyNames ( proto ) . sort ( ) . join ( '\0' ) !==
73101 object_proto_names
74102 ) {
75- throw new Error ( `Cannot stringify arbitrary non-POJOs` ) ;
103+ throw new DevalueError (
104+ `Cannot stringify arbitrary non-POJOs` ,
105+ keys
106+ ) ;
76107 }
77108
78109 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+ ) ;
80114 }
81115
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+ }
83121 }
84122 }
85123 }
0 commit comments