@@ -792,6 +792,8 @@ const TEST_CASES_PARSER = [
792792 { input : '"hello world"' , expected : Cl . stringAscii ( 'hello world' ) } ,
793793 { input : 'u"hello world"' , expected : Cl . stringUtf8 ( 'hello world' ) } ,
794794 { input : '"hello \\"world\\""' , expected : Cl . stringAscii ( 'hello "world"' ) } ,
795+ { input : '"hello \\\\"' , expected : Cl . stringAscii ( 'hello \\' ) } ,
796+ { input : '"hello \\\\\\", \\"world\\""' , expected : Cl . stringAscii ( 'hello \\", "world"' ) } ,
795797 { input : '(list 1 2 3)' , expected : Cl . list ( [ Cl . int ( 1 ) , Cl . int ( 2 ) , Cl . int ( 3 ) ] ) } ,
796798 { input : '( list 1 2 3 )' , expected : Cl . list ( [ Cl . int ( 1 ) , Cl . int ( 2 ) , Cl . int ( 3 ) ] ) } ,
797799 { input : '( list )' , expected : Cl . list ( [ ] ) } ,
@@ -830,11 +832,58 @@ const TEST_CASES_PARSER = [
830832 ] )
831833 ) ,
832834 } ,
835+ { input : 'u""' , expected : Cl . stringUtf8 ( '' ) } ,
836+ { input : 'u"\\\\"' , expected : Cl . stringUtf8 ( '\\' ) } ,
837+ { input : `u"\\n"` , expected : Cl . stringUtf8 ( '\n' ) } ,
833838] as const ;
834839
835- test . each ( TEST_CASES_PARSER ) ( 'clarity parser %p' , ( { input, expected } ) => {
836- const result = parse ( input ) ;
837- expect ( result ) . toEqual ( expected ) ;
840+ const TEST_CASES_PARSER_INVERTIBLE = [
841+ { input : '""' , expected : Cl . stringAscii ( '' ) } ,
842+ { input : '"hello"' , expected : Cl . stringAscii ( 'hello' ) } ,
843+ { input : '"\\"hello\\""' , expected : Cl . stringAscii ( '"hello"' ) } ,
844+ { input : '"a\\\\b"' , expected : Cl . stringAscii ( 'a\\b' ) } ,
845+ { input : 'u"a\\\\\\\\b"' , expected : Cl . stringUtf8 ( 'a\\\\b' ) } ,
846+ { input : 'u"a\\"b"' , expected : Cl . stringUtf8 ( 'a"b' ) } ,
847+ { input : 'u"こんにちは"' , expected : Cl . stringUtf8 ( 'こんにちは' ) } ,
848+
849+ { input : '"\\\\path\\\\to\\\\file"' , expected : Cl . stringAscii ( '\\path\\to\\file' ) } ,
850+ { input : '"\\b\\f\\n\\r\\t\\"\\\\"' , expected : Cl . stringAscii ( '\b\f\n\r\t"\\' ) } ,
851+
852+ {
853+ input : '"Line1\\nLine2\\u0002 \\"Quote\\" \\\\ slash"' ,
854+ expected : Cl . stringAscii ( 'Line1\nLine2\u0002 "Quote" \\ slash' ) ,
855+ } ,
856+
857+ { input : 'u"résumé – ångström"' , expected : Cl . stringUtf8 ( 'résumé – ångström' ) } ,
858+ ] as const ;
859+
860+ test . each ( [ ...TEST_CASES_PARSER , ...TEST_CASES_PARSER_INVERTIBLE ] ) (
861+ 'clarity parser %p' ,
862+ ( { input, expected } ) => {
863+ const result = parse ( input ) ;
864+ expect ( result ) . toEqual ( expected ) ;
865+ }
866+ ) ;
867+
868+ test . each ( TEST_CASES_PARSER_INVERTIBLE ) ( 'clarity parser inverseable %p' , ( { input, expected } ) => {
869+ const parsed = parse ( input ) ;
870+ expect ( parsed ) . toEqual ( expected ) ;
871+
872+ const stringified = Cl . stringify ( parsed ) ;
873+ expect ( stringified ) . toEqual ( input ) ;
838874} ) ;
839875
876+ test . each ( TEST_CASES_PARSER_INVERTIBLE ) (
877+ 'clarity parser string handling matches JSON JS implementation %p' ,
878+ ( { input, expected } ) => {
879+ if ( expected . type !== 'utf8' && expected . type !== 'ascii' ) return ; // Only strings
880+ if ( expected . type === 'utf8' ) input = input . replace ( 'u"' , '"' ) as any ; // Remove the u" prefix for UTF-8 strings
881+
882+ // String handling in Cl.parse/Cl.stringify should match the JSON.parse/JSON.stringify implementation
883+ const parsed = JSON . parse ( input ) ;
884+ const stringified = JSON . stringify ( parsed ) ;
885+ expect ( stringified ) . toEqual ( input ) ;
886+ }
887+ ) ;
888+
840889// const TEST_CASES_PARSER_THROW = []; // todo: e.g. `{}`
0 commit comments