@@ -180,3 +180,76 @@ describe('nested object', () => {
180180 } ) ;
181181 } ) ;
182182} ) ;
183+
184+ describe ( 'buffer reallocation stress tests' , ( ) => {
185+ test ( 'strings with non-ASCII triggering fallback (reproduces writer.x bug)' , ( ) => {
186+ // This specifically tests the bug where writer.x is not reset before fallback
187+ // When a short string (<256) contains non-ASCII, it triggers writer.utf8()
188+ // but writer.x has already been incremented by writing the opening quote
189+ for ( let round = 0 ; round < 50 ; round ++ ) {
190+ const smallWriter = new Writer ( 64 ) ;
191+ const smallEncoder = new JsonEncoder ( smallWriter ) ;
192+
193+ for ( let i = 0 ; i < 500 ; i ++ ) {
194+ // Create strings < 256 chars with non-ASCII character to trigger fallback
195+ const asciiPart = 'a' . repeat ( Math . floor ( Math . random ( ) * 200 ) ) ;
196+ const value = { foo : asciiPart + '\u0001' + asciiPart } ; // control char triggers fallback
197+ const encoded = smallEncoder . encode ( value ) ;
198+ const json = Buffer . from ( encoded ) . toString ( 'utf-8' ) ;
199+ const decoded = JSON . parse ( json ) ;
200+ expect ( decoded ) . toEqual ( value ) ;
201+ }
202+ }
203+ } ) ;
204+
205+ test ( 'many iterations with long strings (reproduces writer.utf8 bug)' , ( ) => {
206+ // Run multiple test rounds to increase chance of hitting the bug
207+ for ( let round = 0 ; round < 10 ; round ++ ) {
208+ const smallWriter = new Writer ( 64 ) ;
209+ const smallEncoder = new JsonEncoder ( smallWriter ) ;
210+
211+ for ( let i = 0 ; i < 1000 ; i ++ ) {
212+ const value = {
213+ foo : 'a' . repeat ( Math . round ( 32000 * Math . random ( ) ) + 10 ) ,
214+ } ;
215+ const encoded = smallEncoder . encode ( value ) ;
216+ const json = Buffer . from ( encoded ) . toString ( 'utf-8' ) ;
217+ const decoded = JSON . parse ( json ) ;
218+ expect ( decoded ) . toEqual ( value ) ;
219+ }
220+ }
221+ } ) ;
222+
223+ test ( 'repeated long strings >= 256 chars (reproduces writer.utf8 bug)' , ( ) => {
224+ // Run multiple test rounds to increase chance of hitting the bug
225+ for ( let round = 0 ; round < 20 ; round ++ ) {
226+ const smallWriter = new Writer ( 64 ) ;
227+ const smallEncoder = new JsonEncoder ( smallWriter ) ;
228+
229+ for ( let i = 0 ; i < 100 ; i ++ ) {
230+ const length = 256 + Math . floor ( Math . random ( ) * 10000 ) ;
231+ const value = { foo : 'a' . repeat ( length ) } ;
232+ const encoded = smallEncoder . encode ( value ) ;
233+ const json = Buffer . from ( encoded ) . toString ( 'utf-8' ) ;
234+ const decoded = JSON . parse ( json ) ;
235+ expect ( decoded ) . toEqual ( value ) ;
236+ }
237+ }
238+ } ) ;
239+
240+ test ( 'many short strings with buffer growth (reproduces writer.utf8 bug)' , ( ) => {
241+ // Run multiple test rounds to increase chance of hitting the bug
242+ for ( let round = 0 ; round < 10 ; round ++ ) {
243+ const smallWriter = new Writer ( 64 ) ;
244+ const smallEncoder = new JsonEncoder ( smallWriter ) ;
245+
246+ for ( let i = 0 ; i < 1000 ; i ++ ) {
247+ const value = { foo : 'test' + i } ;
248+ const encoded = smallEncoder . encode ( value ) ;
249+ const json = Buffer . from ( encoded ) . toString ( 'utf-8' ) ;
250+ const decoded = JSON . parse ( json ) ;
251+ expect ( decoded ) . toEqual ( value ) ;
252+ }
253+ }
254+ } ) ;
255+ } ) ;
0 commit comments