@@ -50,10 +50,21 @@ const {
5050 TypedArrayPrototypeGetByteOffset,
5151 TypedArrayPrototypeGetLength,
5252 TypedArrayPrototypeSet,
53- TypedArrayPrototypeSlice,
5453 Uint8Array,
54+ Uint8ArrayPrototype,
55+ uncurryThis,
5556} = primordials ;
5657
58+ // Lazily initialized: toHex is installed by InitializeExperimentalGlobal()
59+ // (skipped during snapshot creation) and may be disabled with --no-js-base-64.
60+ let Uint8ArrayPrototypeToHex ;
61+ function ensureUint8ArrayToHex ( ) {
62+ if ( Uint8ArrayPrototypeToHex === undefined ) {
63+ Uint8ArrayPrototypeToHex = Uint8ArrayPrototype . toHex ?
64+ uncurryThis ( Uint8ArrayPrototype . toHex ) : null ;
65+ }
66+ }
67+
5768const {
5869 byteLengthUtf8,
5970 compare : _compare ,
@@ -382,28 +393,41 @@ Buffer.copyBytesFrom = function copyBytesFrom(view, offset, length) {
382393 return new FastBuffer ( ) ;
383394 }
384395
396+ const byteLength = TypedArrayPrototypeGetByteLength ( view ) ;
397+
385398 if ( offset !== undefined || length !== undefined ) {
386399 if ( offset !== undefined ) {
387400 validateInteger ( offset , 'offset' , 0 ) ;
388401 if ( offset >= viewLength ) return new FastBuffer ( ) ;
389402 } else {
390403 offset = 0 ;
391404 }
405+
392406 let end ;
393407 if ( length !== undefined ) {
394408 validateInteger ( length , 'length' , 0 ) ;
395- end = offset + length ;
409+ end = MathMin ( offset + length , viewLength ) ;
396410 } else {
397411 end = viewLength ;
398412 }
399413
400- view = TypedArrayPrototypeSlice ( view , offset , end ) ;
414+ if ( end <= offset ) return new FastBuffer ( ) ;
415+
416+ const elementSize = byteLength / viewLength ;
417+ const srcByteOffset = TypedArrayPrototypeGetByteOffset ( view ) +
418+ offset * elementSize ;
419+ const srcByteLength = ( end - offset ) * elementSize ;
420+
421+ return fromArrayLike ( new Uint8Array (
422+ TypedArrayPrototypeGetBuffer ( view ) ,
423+ srcByteOffset ,
424+ srcByteLength ) ) ;
401425 }
402426
403427 return fromArrayLike ( new Uint8Array (
404428 TypedArrayPrototypeGetBuffer ( view ) ,
405429 TypedArrayPrototypeGetByteOffset ( view ) ,
406- TypedArrayPrototypeGetByteLength ( view ) ) ) ;
430+ byteLength ) ) ;
407431} ;
408432
409433// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated
@@ -550,14 +574,15 @@ function fromArrayBuffer(obj, byteOffset, length) {
550574}
551575
552576function fromArrayLike ( obj ) {
553- if ( obj . length <= 0 )
577+ const len = obj . length ;
578+ if ( len <= 0 )
554579 return new FastBuffer ( ) ;
555- if ( obj . length < ( Buffer . poolSize >>> 1 ) ) {
556- if ( obj . length > ( poolSize - poolOffset ) )
580+ if ( len < ( Buffer . poolSize >>> 1 ) ) {
581+ if ( len > ( poolSize - poolOffset ) )
557582 createPool ( ) ;
558- const b = new FastBuffer ( allocPool , poolOffset , obj . length ) ;
583+ const b = new FastBuffer ( allocPool , poolOffset , len ) ;
559584 TypedArrayPrototypeSet ( b , obj , 0 ) ;
560- poolOffset += obj . length ;
585+ poolOffset += len ;
561586 alignPool ( ) ;
562587 return b ;
563588 }
@@ -657,6 +682,18 @@ function base64ByteLength(str, bytes) {
657682 return ( bytes * 3 ) >>> 2 ;
658683}
659684
685+ function hexSliceToHex ( buf , start , end ) {
686+ ensureUint8ArrayToHex ( ) ;
687+ // Fall back to C++ when toHex is unavailable or the result would exceed
688+ // kStringMaxLength (so the correct ERR_STRING_TOO_LONG error is thrown).
689+ if ( Uint8ArrayPrototypeToHex === null || ( end - start ) * 2 > kStringMaxLength )
690+ return hexSlice ( buf , start , end ) ;
691+ return Uint8ArrayPrototypeToHex (
692+ new Uint8Array ( TypedArrayPrototypeGetBuffer ( buf ) ,
693+ TypedArrayPrototypeGetByteOffset ( buf ) + start ,
694+ end - start ) ) ;
695+ }
696+
660697const encodingOps = {
661698 utf8 : {
662699 encoding : 'utf8' ,
@@ -701,11 +738,7 @@ const encodingOps = {
701738 write : asciiWrite ,
702739 slice : asciiSlice ,
703740 indexOf : ( buf , val , byteOffset , dir ) =>
704- indexOfBuffer ( buf ,
705- fromStringFast ( val , encodingOps . ascii ) ,
706- byteOffset ,
707- encodingsMap . ascii ,
708- dir ) ,
741+ indexOfString ( buf , val , byteOffset , encodingsMap . latin1 , dir ) ,
709742 } ,
710743 base64 : {
711744 encoding : 'base64' ,
@@ -738,7 +771,7 @@ const encodingOps = {
738771 encodingVal : encodingsMap . hex ,
739772 byteLength : ( string ) => string . length >>> 1 ,
740773 write : hexWrite ,
741- slice : hexSlice ,
774+ slice : hexSliceToHex ,
742775 indexOf : ( buf , val , byteOffset , dir ) =>
743776 indexOfBuffer ( buf ,
744777 fromStringFast ( val , encodingOps . hex ) ,
@@ -1087,7 +1120,7 @@ function _fill(buf, value, offset, end, encoding) {
10871120 value = 0 ;
10881121 } else if ( value . length === 1 ) {
10891122 // Fast path: If `value` fits into a single byte, use that numeric value.
1090- if ( normalizedEncoding === 'utf8' ) {
1123+ if ( normalizedEncoding === 'utf8' || normalizedEncoding === 'ascii' ) {
10911124 const code = StringPrototypeCharCodeAt ( value , 0 ) ;
10921125 if ( code < 128 ) {
10931126 value = code ;
@@ -1137,29 +1170,30 @@ function _fill(buf, value, offset, end, encoding) {
11371170}
11381171
11391172Buffer . prototype . write = function write ( string , offset , length , encoding ) {
1173+ const len = this . length ;
11401174 // Buffer#write(string);
11411175 if ( offset === undefined ) {
1142- return utf8Write ( this , string , 0 , this . length ) ;
1176+ return utf8Write ( this , string , 0 , len ) ;
11431177 }
11441178 // Buffer#write(string, encoding)
11451179 if ( length === undefined && typeof offset === 'string' ) {
11461180 encoding = offset ;
1147- length = this . length ;
1181+ length = len ;
11481182 offset = 0 ;
11491183
11501184 // Buffer#write(string, offset[, length][, encoding])
11511185 } else {
1152- validateOffset ( offset , 'offset' , 0 , this . length ) ;
1186+ validateOffset ( offset , 'offset' , 0 , len ) ;
11531187
1154- const remaining = this . length - offset ;
1188+ const remaining = len - offset ;
11551189
11561190 if ( length === undefined ) {
11571191 length = remaining ;
11581192 } else if ( typeof length === 'string' ) {
11591193 encoding = length ;
11601194 length = remaining ;
11611195 } else {
1162- validateOffset ( length , 'length' , 0 , this . length ) ;
1196+ validateOffset ( length , 'length' , 0 , len ) ;
11631197 if ( length > remaining )
11641198 length = remaining ;
11651199 }
@@ -1177,9 +1211,10 @@ Buffer.prototype.write = function write(string, offset, length, encoding) {
11771211} ;
11781212
11791213Buffer . prototype . toJSON = function toJSON ( ) {
1180- if ( this . length > 0 ) {
1181- const data = new Array ( this . length ) ;
1182- for ( let i = 0 ; i < this . length ; ++ i )
1214+ const len = this . length ;
1215+ if ( len > 0 ) {
1216+ const data = new Array ( len ) ;
1217+ for ( let i = 0 ; i < len ; ++ i )
11831218 data [ i ] = this [ i ] ;
11841219 return { type : 'Buffer' , data } ;
11851220 }
@@ -1233,7 +1268,8 @@ Buffer.prototype.swap16 = function swap16() {
12331268 swap ( this , i , i + 1 ) ;
12341269 return this ;
12351270 }
1236- return _swap16 ( this ) ;
1271+ _swap16 ( this ) ;
1272+ return this ;
12371273} ;
12381274
12391275Buffer . prototype . swap32 = function swap32 ( ) {
@@ -1250,7 +1286,8 @@ Buffer.prototype.swap32 = function swap32() {
12501286 }
12511287 return this ;
12521288 }
1253- return _swap32 ( this ) ;
1289+ _swap32 ( this ) ;
1290+ return this ;
12541291} ;
12551292
12561293Buffer . prototype . swap64 = function swap64 ( ) {
@@ -1269,7 +1306,8 @@ Buffer.prototype.swap64 = function swap64() {
12691306 }
12701307 return this ;
12711308 }
1272- return _swap64 ( this ) ;
1309+ _swap64 ( this ) ;
1310+ return this ;
12731311} ;
12741312
12751313Buffer . prototype . toLocaleString = Buffer . prototype . toString ;
0 commit comments