@@ -73,6 +73,7 @@ const State = {
7373 objectMemberValue : 'objectMemberValue' ,
7474 string : 'string' ,
7575 escape : 'escape' ,
76+ escapeUnicode : 'escapeUnicode' ,
7677 array : 'array' ,
7778 arrayItem : 'arrayItem' ,
7879 literal : 'literal' ,
@@ -192,7 +193,7 @@ export class JSON22 {
192193 // ignore
193194 break ;
194195 case QUOTATION_MARK :
195- valueStack . push ( [ ] ) ;
196+ valueStack . push ( [ { start : i , end : i , type : 'string' } ] ) ;
196197 stateStack . push ( State . string ) ;
197198 break ;
198199 case BEGIN_OBJECT :
@@ -250,44 +251,55 @@ export class JSON22 {
250251 case ( code < 0x20 ? c : undefined ) :
251252 throw new Error ( `Character ${ c } at position ${ i } is not allowed, try to escape it` ) ;
252253 case ESCAPE_CHAR :
254+ const region = valueStack . top . pop ( ) ;
255+ valueStack . top . push ( text . slice ( region . start + 1 , region . end + 1 ) ) ;
253256 stateStack . push ( State . escape ) ;
254257 break ;
255258 case QUOTATION_MARK :
256- const chars = valueStack . pop ( ) ;
257- const value = chars . join ( '' ) ;
259+ const r = valueStack . top . pop ( ) ;
260+ valueStack . top . push ( text . slice ( r . start + 1 , r . end + 1 ) ) ;
261+ const substrings = valueStack . pop ( ) ;
262+ const value = substrings . join ( '' ) ;
258263 valueStack . push ( value ) ;
259264 stateStack . pop ( State . string ) ;
260265 stateStack . pop ( ) ; // out of value or objectMemberKey
261266 break ;
262267 default :
263- valueStack . top . push ( c ) ;
268+ valueStack . top [ valueStack . top . length - 1 ] . end = i ;
264269 break ;
265270 }
266271 break ;
267272 case State . escape :
268273 switch ( c ) {
269274 case ( ESCAPE_SHORTENS . indexOf ( c ) > - 1 ? c : undefined ) :
270275 valueStack . top . push ( ESCAPE_MAP [ c ] ) ;
276+ valueStack . top . push ( { start : i , end : i , type : 'string' } ) ;
271277 stateStack . pop ( ) ;
272278 break ;
273279 case 'u' : // unicode escape like \u0020
274- valueStack . push ( [ 'unicode' ] ) ;
280+ valueStack . top . push ( { start : i , end : i , type : 'escapeUnicode' } ) ;
281+ stateStack . switch ( State . escape , State . escapeUnicode ) ;
275282 break ;
283+ default :
284+ throw new Error ( `Unexpected character ${ c } at ${ i } , escape sequence expected` ) ;
285+ }
286+ break ;
287+ case State . escapeUnicode :
288+ switch ( c ) {
276289 case ( HEXADECIMALS . indexOf ( c ) > - 1 ? c : undefined ) :
277- if ( valueStack . top [ 0 ] === 'unicode' ) {
278- if ( valueStack . top . length === 5 ) {
279- const top = valueStack . pop ( ) ;
280- top . shift ( ) ;
281- const code = parseInt ( top . join ( '' ) , 16 ) ;
282- valueStack . top . push ( String . fromCharCode ( code ) ) ;
283- stateStack . pop ( ) ;
284- }
285- } else {
286- throw new Error ( `Unexpected character ${ c } at ${ i } , unicode escape sequence expected` ) ;
290+ const region = valueStack . top [ valueStack . top . length - 1 ] ;
291+ region . end = i ;
292+ if ( region . end - region . start === 4 ) {
293+ valueStack . top . pop ( ) ;
294+ const codeText = text . slice ( region . start + 1 , region . end + 1 ) ;
295+ const code = parseInt ( codeText , 16 ) ;
296+ valueStack . top . push ( String . fromCharCode ( code ) ) ;
297+ valueStack . top . push ( { start : i , end : i , type : 'string' } ) ;
298+ stateStack . pop ( State . escapeUnicode ) ;
287299 }
288300 break ;
289301 default :
290- throw new Error ( `Unexpected character ${ c } at ${ i } , escape sequence expected` ) ;
302+ throw new Error ( `Unexpected character ${ c } at ${ i } , unicode escape sequence expected` ) ;
291303 }
292304 break ;
293305 case State . object :
@@ -309,7 +321,7 @@ export class JSON22 {
309321 // ignore
310322 break ;
311323 case QUOTATION_MARK :
312- valueStack . push ( [ ] ) ;
324+ valueStack . push ( [ { start : i , end : i , type : 'string' } ] ) ;
313325 stateStack . push ( State . string ) ;
314326 break ;
315327 case END_OBJECT :
0 commit comments