@@ -278,7 +278,8 @@ function ReadableState(options, stream, isDuplex) {
278
278
// A linked list is used to store data chunks instead of an array because the
279
279
// linked list can remove elements from the beginning faster than
280
280
// array.shift().
281
- this . buffer = new BufferList ( ) ;
281
+ this . buffer = [ ] ;
282
+ this . bufferIndex = 0 ;
282
283
this . length = 0 ;
283
284
this . pipes = [ ] ;
284
285
@@ -546,10 +547,15 @@ function addChunk(stream, state, chunk, addToFront) {
546
547
} else {
547
548
// Update the buffer info.
548
549
state . length += ( state [ kState ] & kObjectMode ) !== 0 ? 1 : chunk . length ;
549
- if ( addToFront )
550
- state . buffer . unshift ( chunk ) ;
551
- else
550
+ if ( addToFront ) {
551
+ if ( state . bufferIndex > 0 ) {
552
+ state . buffer [ -- state . bufferIndex ] = chunk ;
553
+ } else {
554
+ state . buffer . unshift ( chunk ) ; // Slow path
555
+ }
556
+ } else {
552
557
state . buffer . push ( chunk ) ;
558
+ }
553
559
554
560
if ( ( state [ kState ] & kNeedReadable ) !== 0 )
555
561
emitReadable ( stream ) ;
@@ -564,21 +570,24 @@ Readable.prototype.isPaused = function() {
564
570
565
571
// Backwards compatibility.
566
572
Readable . prototype . setEncoding = function ( enc ) {
573
+ const state = this . _readableState ;
574
+
567
575
const decoder = new StringDecoder ( enc ) ;
568
- this . _readableState . decoder = decoder ;
576
+ state . decoder = decoder ;
569
577
// If setEncoding(null), decoder.encoding equals utf8.
570
- this . _readableState . encoding = this . _readableState . decoder . encoding ;
578
+ state . encoding = state . decoder . encoding ;
571
579
572
- const buffer = this . _readableState . buffer ;
573
580
// Iterate over current buffer to convert already stored Buffers:
574
581
let content = '' ;
575
- for ( const data of buffer ) {
582
+ for ( const data of state . buffer . slice ( state . bufferIndex ) ) {
576
583
content += decoder . write ( data ) ;
577
584
}
578
- buffer . clear ( ) ;
585
+ state . buffer . length = 0 ;
586
+ state . bufferIndex = 0 ;
587
+
579
588
if ( content !== '' )
580
589
buffer . push ( content ) ;
581
- this . _readableState . length = content . length ;
590
+ state . length = content . length ;
582
591
return this ;
583
592
} ;
584
593
@@ -611,7 +620,7 @@ function howMuchToRead(n, state) {
611
620
if ( NumberIsNaN ( n ) ) {
612
621
// Only flow one buffer at a time.
613
622
if ( ( state [ kState ] & kFlowing ) !== 0 && state . length )
614
- return state . buffer . first ( ) . length ;
623
+ return state . buffer [ state . bufferIndex ] . length ;
615
624
return state . length ;
616
625
}
617
626
if ( n <= state . length )
@@ -1550,20 +1559,96 @@ function fromList(n, state) {
1550
1559
return null ;
1551
1560
1552
1561
let ret ;
1553
- if ( state . objectMode )
1554
- ret = state . buffer . shift ( ) ;
1555
- else if ( ! n || n >= state . length ) {
1562
+ if ( ( state [ kState ] & kObjectMode ) !== 0 ) {
1563
+ ret = state . buffer [ state . bufferIndex ++ ] ;
1564
+ } else if ( ! n || n >= state . length ) {
1556
1565
// Read it all, truncate the list.
1557
- if ( state . decoder )
1558
- ret = state . buffer . join ( '' ) ;
1559
- else if ( state . buffer . length === 1 )
1560
- ret = state . buffer . first ( ) ;
1561
- else
1562
- ret = state . buffer . concat ( state . length ) ;
1563
- state . buffer . clear ( ) ;
1566
+ if ( ( state [ kState ] & kDecoder ) !== 0 ) {
1567
+ ret = ''
1568
+ for ( let n = state . bufferIndex ; n < state . buffer . length ; n ++ ) {
1569
+ ret += state . buffer [ n ] ;
1570
+ }
1571
+ } else if ( state . buffer . length - state . bufferIndex === 0 ) {
1572
+ ret = Buffer . alloc ( 0 )
1573
+ } else if ( state . buffer . length - state . bufferIndex === 1 ) {
1574
+ ret = state . buffer [ state . bufferIndex ] ;
1575
+ } else {
1576
+ ret = Buffer . allocUnsafe ( n >>> 0 ) ;
1577
+ let i = 0 ;
1578
+ for ( let n = state . bufferIndex ; n < state . buffer . length ; n ++ ) {
1579
+ const data = state . buffer [ n ] ;
1580
+ ret . set ( data , i ) ;
1581
+ i += data . length ;
1582
+ }
1583
+ }
1584
+ state . buffer . length = 0 ;
1585
+ state . bufferIndex = 0 ;
1564
1586
} else {
1565
1587
// read part of list.
1566
- ret = state . buffer . consume ( n , state . decoder ) ;
1588
+
1589
+ const data = state . buffer [ state . bufferIndex ] ;
1590
+
1591
+ if ( n < data . length ) {
1592
+ // `slice` is the same for buffers and strings.
1593
+ const slice = data . slice ( 0 , n ) ;
1594
+ state . buffer [ state . bufferIndex ] = data . slice ( n ) ;
1595
+ return slice ;
1596
+ }
1597
+
1598
+ if ( n === data . length ) {
1599
+ // First chunk is a perfect match.
1600
+ return state . buffer [ state . bufferIndex ++ ] ;
1601
+ }
1602
+
1603
+ if ( ( state [ kState ] & kDecoder ) !== 0 ) {
1604
+ ret = '' ;
1605
+ while ( state . bufferIndex < state . buffer . length ) {
1606
+ const str = state . buffer [ state . bufferIndex ] ;
1607
+ if ( n > str . length ) {
1608
+ ret += str ;
1609
+ n -= str . length ;
1610
+ state . bufferIndex ++ ;
1611
+ } else {
1612
+ if ( n === buf . length ) {
1613
+ ret += str ;
1614
+ state . bufferIndex ++ ;
1615
+ } else {
1616
+ ret += str . slice ( 0 , n ) ;
1617
+ state . buffer [ state . bufferIndex ] = str . slice ( n ) ;
1618
+ }
1619
+ break ;
1620
+ }
1621
+ }
1622
+ } else {
1623
+ ret = Buffer . allocUnsafe ( n ) ;
1624
+
1625
+ const retLen = n ;
1626
+ while ( state . bufferIndex < state . buffer . length ) {
1627
+ const buf = state . buffer [ state . bufferIndex ] ;
1628
+ if ( n > buf . length ) {
1629
+ ret . set ( buf , retLen - n ) ;
1630
+ n -= buf . length ;
1631
+ state . bufferIndex ++ ;
1632
+ } else {
1633
+ if ( n === buf . length ) {
1634
+ ret . set ( buf , retLen - n ) ;
1635
+ state . bufferIndex ++ ;
1636
+ } else {
1637
+ ret . set ( new Uint8Array ( buf . buffer , buf . byteOffset , n ) , retLen - n ) ;
1638
+ state . buffer [ state . bufferIndex ] = buf . slice ( n ) ;
1639
+ }
1640
+ break ;
1641
+ }
1642
+ }
1643
+ }
1644
+
1645
+ if ( state . bufferIndex === state . buffer . length ) {
1646
+ state . buffer . length = 0 ;
1647
+ state . bufferIndex = 0
1648
+ } else if ( state . bufferIndex > 256 ) {
1649
+ state . buffer = state . buffer . slice ( state . bufferIndex ) ;
1650
+ state . bufferIndex = 0 ;
1651
+ }
1567
1652
}
1568
1653
1569
1654
return ret ;
0 commit comments