@@ -50,7 +50,6 @@ const {
5050 TypedArrayPrototypeGetByteOffset,
5151 TypedArrayPrototypeGetLength,
5252 TypedArrayPrototypeSet,
53- TypedArrayPrototypeSlice,
5453 TypedArrayPrototypeSubarray,
5554 Uint8Array,
5655} = primordials ;
@@ -383,28 +382,33 @@ Buffer.copyBytesFrom = function copyBytesFrom(view, offset, length) {
383382 return new FastBuffer ( ) ;
384383 }
385384
386- if ( offset !== undefined || length !== undefined ) {
387- if ( offset !== undefined ) {
388- validateInteger ( offset , 'offset' , 0 ) ;
389- if ( offset >= viewLength ) return new FastBuffer ( ) ;
390- } else {
391- offset = 0 ;
392- }
393- let end ;
394- if ( length !== undefined ) {
395- validateInteger ( length , 'length' , 0 ) ;
396- end = offset + length ;
397- } else {
398- end = viewLength ;
399- }
385+ let start = 0 ;
386+ let end = viewLength ;
400387
401- view = TypedArrayPrototypeSlice ( view , offset , end ) ;
388+ if ( offset !== undefined ) {
389+ validateInteger ( offset , 'offset' , 0 ) ;
390+ if ( offset >= viewLength ) return new FastBuffer ( ) ;
391+ start = offset ;
402392 }
403393
394+ if ( length !== undefined ) {
395+ validateInteger ( length , 'length' , 0 ) ;
396+ // The old code used TypedArrayPrototypeSlice which clamps internally.
397+ end = MathMin ( start + length , viewLength ) ;
398+ }
399+
400+ if ( end <= start ) return new FastBuffer ( ) ;
401+
402+ const viewByteLength = TypedArrayPrototypeGetByteLength ( view ) ;
403+ const elementSize = viewByteLength / viewLength ;
404+ const srcByteOffset = TypedArrayPrototypeGetByteOffset ( view ) +
405+ start * elementSize ;
406+ const srcByteLength = ( end - start ) * elementSize ;
407+
404408 return fromArrayLike ( new Uint8Array (
405409 TypedArrayPrototypeGetBuffer ( view ) ,
406- TypedArrayPrototypeGetByteOffset ( view ) ,
407- TypedArrayPrototypeGetByteLength ( view ) ) ) ;
410+ srcByteOffset ,
411+ srcByteLength ) ) ;
408412} ;
409413
410414// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated
@@ -551,14 +555,15 @@ function fromArrayBuffer(obj, byteOffset, length) {
551555}
552556
553557function fromArrayLike ( obj ) {
554- if ( obj . length <= 0 )
558+ const { length } = obj ;
559+ if ( length <= 0 )
555560 return new FastBuffer ( ) ;
556- if ( obj . length < ( Buffer . poolSize >>> 1 ) ) {
557- if ( obj . length > ( poolSize - poolOffset ) )
561+ if ( length < ( Buffer . poolSize >>> 1 ) ) {
562+ if ( length > ( poolSize - poolOffset ) )
558563 createPool ( ) ;
559- const b = new FastBuffer ( allocPool , poolOffset , obj . length ) ;
564+ const b = new FastBuffer ( allocPool , poolOffset , length ) ;
560565 TypedArrayPrototypeSet ( b , obj , 0 ) ;
561- poolOffset += obj . length ;
566+ poolOffset += length ;
562567 alignPool ( ) ;
563568 return b ;
564569 }
@@ -732,11 +737,7 @@ const encodingOps = {
732737 write : asciiWrite ,
733738 slice : asciiSlice ,
734739 indexOf : ( buf , val , byteOffset , dir ) =>
735- indexOfBuffer ( buf ,
736- fromStringFast ( val , encodingOps . ascii ) ,
737- byteOffset ,
738- encodingsMap . ascii ,
739- dir ) ,
740+ indexOfString ( buf , val , byteOffset , encodingsMap . ascii , dir ) ,
740741 } ,
741742 base64 : {
742743 encoding : 'base64' ,
@@ -897,17 +898,17 @@ Buffer.prototype.toString = function toString(encoding, start, end) {
897898 return utf8Slice ( this , 0 , this . length ) ;
898899 }
899900
900- const len = this . length ;
901+ const bufferLength = TypedArrayPrototypeGetLength ( this ) ;
901902
902903 if ( start <= 0 )
903904 start = 0 ;
904- else if ( start >= len )
905+ else if ( start >= bufferLength )
905906 return '' ;
906907 else
907908 start = MathTrunc ( start ) || 0 ;
908909
909- if ( end === undefined || end > len )
910- end = len ;
910+ if ( end === undefined || end > bufferLength )
911+ end = bufferLength ;
911912 else
912913 end = MathTrunc ( end ) || 0 ;
913914
@@ -1118,7 +1119,9 @@ function _fill(buf, value, offset, end, encoding) {
11181119 value = 0 ;
11191120 } else if ( value . length === 1 ) {
11201121 // Fast path: If `value` fits into a single byte, use that numeric value.
1121- if ( normalizedEncoding === 'utf8' ) {
1122+ // ASCII shares this branch with utf8 since code < 128 covers the full
1123+ // ASCII range; anything outside falls through to C++ bindingFill.
1124+ if ( normalizedEncoding === 'utf8' || normalizedEncoding === 'ascii' ) {
11221125 const code = StringPrototypeCharCodeAt ( value , 0 ) ;
11231126 if ( code < 128 ) {
11241127 value = code ;
@@ -1168,29 +1171,30 @@ function _fill(buf, value, offset, end, encoding) {
11681171}
11691172
11701173Buffer . prototype . write = function write ( string , offset , length , encoding ) {
1174+ const bufferLength = TypedArrayPrototypeGetLength ( this ) ;
11711175 // Buffer#write(string);
11721176 if ( offset === undefined ) {
1173- return utf8Write ( this , string , 0 , this . length ) ;
1177+ return utf8Write ( this , string , 0 , bufferLength ) ;
11741178 }
11751179 // Buffer#write(string, encoding)
11761180 if ( length === undefined && typeof offset === 'string' ) {
11771181 encoding = offset ;
1178- length = this . length ;
1182+ length = bufferLength ;
11791183 offset = 0 ;
11801184
11811185 // Buffer#write(string, offset[, length][, encoding])
11821186 } else {
1183- validateOffset ( offset , 'offset' , 0 , this . length ) ;
1187+ validateOffset ( offset , 'offset' , 0 , bufferLength ) ;
11841188
1185- const remaining = this . length - offset ;
1189+ const remaining = bufferLength - offset ;
11861190
11871191 if ( length === undefined ) {
11881192 length = remaining ;
11891193 } else if ( typeof length === 'string' ) {
11901194 encoding = length ;
11911195 length = remaining ;
11921196 } else {
1193- validateOffset ( length , 'length' , 0 , this . length ) ;
1197+ validateOffset ( length , 'length' , 0 , bufferLength ) ;
11941198 if ( length > remaining )
11951199 length = remaining ;
11961200 }
@@ -1208,9 +1212,10 @@ Buffer.prototype.write = function write(string, offset, length, encoding) {
12081212} ;
12091213
12101214Buffer . prototype . toJSON = function toJSON ( ) {
1211- if ( this . length > 0 ) {
1212- const data = new Array ( this . length ) ;
1213- for ( let i = 0 ; i < this . length ; ++ i )
1215+ const bufferLength = TypedArrayPrototypeGetLength ( this ) ;
1216+ if ( bufferLength > 0 ) {
1217+ const data = new Array ( bufferLength ) ;
1218+ for ( let i = 0 ; i < bufferLength ; ++ i )
12141219 data [ i ] = this [ i ] ;
12151220 return { type : 'Buffer' , data } ;
12161221 }
@@ -1235,7 +1240,7 @@ function adjustOffset(offset, length) {
12351240}
12361241
12371242Buffer . prototype . subarray = function subarray ( start , end ) {
1238- const srcLength = this . length ;
1243+ const srcLength = TypedArrayPrototypeGetLength ( this ) ;
12391244 start = adjustOffset ( start , srcLength ) ;
12401245 end = end !== undefined ? adjustOffset ( end , srcLength ) : srcLength ;
12411246 const newLength = end > start ? end - start : 0 ;
@@ -1253,45 +1258,52 @@ function swap(b, n, m) {
12531258}
12541259
12551260Buffer . prototype . swap16 = function swap16 ( ) {
1256- // For Buffer.length < 128, it's generally faster to
1261+ // Ref: https://github.com/nodejs/node/pull/61871#discussion_r2889557696
1262+ // For Buffer.length <= 32, it's generally faster to
12571263 // do the swap in javascript. For larger buffers,
12581264 // dropping down to the native code is faster.
1259- const len = this . length ;
1265+ const len = TypedArrayPrototypeGetLength ( this ) ;
12601266 if ( len % 2 !== 0 )
12611267 throw new ERR_INVALID_BUFFER_SIZE ( '16-bits' ) ;
1262- if ( len < 128 ) {
1268+ if ( len <= 32 ) {
12631269 for ( let i = 0 ; i < len ; i += 2 )
12641270 swap ( this , i , i + 1 ) ;
12651271 return this ;
12661272 }
1267- return _swap16 ( this ) ;
1273+ _swap16 ( this ) ;
1274+ return this ;
12681275} ;
12691276
12701277Buffer . prototype . swap32 = function swap32 ( ) {
1271- // For Buffer.length < 192, it's generally faster to
1278+ // Ref: https://github.com/nodejs/node/pull/61871#discussion_r2889557696
1279+ // For Buffer.length <= 32, it's generally faster to
12721280 // do the swap in javascript. For larger buffers,
12731281 // dropping down to the native code is faster.
1274- const len = this . length ;
1282+ const len = TypedArrayPrototypeGetLength ( this ) ;
12751283 if ( len % 4 !== 0 )
12761284 throw new ERR_INVALID_BUFFER_SIZE ( '32-bits' ) ;
1277- if ( len < 192 ) {
1285+ if ( len <= 32 ) {
12781286 for ( let i = 0 ; i < len ; i += 4 ) {
12791287 swap ( this , i , i + 3 ) ;
12801288 swap ( this , i + 1 , i + 2 ) ;
12811289 }
12821290 return this ;
12831291 }
1284- return _swap32 ( this ) ;
1292+ _swap32 ( this ) ;
1293+ return this ;
12851294} ;
12861295
12871296Buffer . prototype . swap64 = function swap64 ( ) {
1288- // For Buffer.length < 192, it's generally faster to
1297+ // Ref: https://github.com/nodejs/node/pull/61871#discussion_r2889557696
1298+ // For Buffer.length < 48, it's generally faster to
12891299 // do the swap in javascript. For larger buffers,
12901300 // dropping down to the native code is faster.
1291- const len = this . length ;
1301+ // Threshold differs from swap16/swap32 (<=32) because swap64's
1302+ // crossover is between 40 and 48 (native wins at 48, loses at 40).
1303+ const len = TypedArrayPrototypeGetLength ( this ) ;
12921304 if ( len % 8 !== 0 )
12931305 throw new ERR_INVALID_BUFFER_SIZE ( '64-bits' ) ;
1294- if ( len < 192 ) {
1306+ if ( len < 48 ) {
12951307 for ( let i = 0 ; i < len ; i += 8 ) {
12961308 swap ( this , i , i + 7 ) ;
12971309 swap ( this , i + 1 , i + 6 ) ;
@@ -1300,7 +1312,8 @@ Buffer.prototype.swap64 = function swap64() {
13001312 }
13011313 return this ;
13021314 }
1303- return _swap64 ( this ) ;
1315+ _swap64 ( this ) ;
1316+ return this ;
13041317} ;
13051318
13061319Buffer . prototype . toLocaleString = Buffer . prototype . toString ;
0 commit comments