2
2
'use strict' ;
3
3
4
4
const binding = process . binding ( 'buffer' ) ;
5
+ const { isArrayBuffer } = process . binding ( 'util' ) ;
5
6
const bindingObj = { } ;
6
7
8
+ class FastBuffer extends Uint8Array { }
9
+
10
+ FastBuffer . prototype . constructor = Buffer ;
11
+ Buffer . prototype = FastBuffer . prototype ;
12
+
7
13
exports . Buffer = Buffer ;
8
14
exports . SlowBuffer = SlowBuffer ;
9
15
exports . INSPECT_MAX_BYTES = 50 ;
@@ -63,24 +69,18 @@ Buffer.prototype.swap32 = function swap32() {
63
69
// do not own the ArrayBuffer allocator. Zero fill is always on in that case.
64
70
const zeroFill = bindingObj . zeroFill || [ 0 ] ;
65
71
66
- function createBuffer ( size , noZeroFill ) {
67
- if ( noZeroFill )
68
- zeroFill [ 0 ] = 0 ;
69
-
72
+ function createUnsafeBuffer ( size ) {
73
+ zeroFill [ 0 ] = 0 ;
70
74
try {
71
- var ui8 = new Uint8Array ( size ) ;
75
+ return new FastBuffer ( size ) ;
72
76
} finally {
73
- if ( noZeroFill )
74
- zeroFill [ 0 ] = 1 ;
77
+ zeroFill [ 0 ] = 1 ;
75
78
}
76
-
77
- Object . setPrototypeOf ( ui8 , Buffer . prototype ) ;
78
- return ui8 ;
79
79
}
80
80
81
81
function createPool ( ) {
82
82
poolSize = Buffer . poolSize ;
83
- allocPool = createBuffer ( poolSize , true ) ;
83
+ allocPool = createUnsafeBuffer ( poolSize ) ;
84
84
poolOffset = 0 ;
85
85
}
86
86
createPool ( ) ;
@@ -138,7 +138,6 @@ Buffer.from = function(value, encodingOrOffset, length) {
138
138
return fromObject ( value ) ;
139
139
} ;
140
140
141
- Object . setPrototypeOf ( Buffer . prototype , Uint8Array . prototype ) ;
142
141
Object . setPrototypeOf ( Buffer , Uint8Array ) ;
143
142
144
143
function assertSize ( size ) {
@@ -158,18 +157,16 @@ function assertSize(size) {
158
157
**/
159
158
Buffer . alloc = function ( size , fill , encoding ) {
160
159
assertSize ( size ) ;
161
- if ( size <= 0 )
162
- return createBuffer ( size ) ;
163
- if ( fill !== undefined ) {
160
+ if ( size > 0 && fill !== undefined ) {
164
161
// Since we are filling anyway, don't zero fill initially.
165
162
// Only pay attention to encoding if it's a string. This
166
163
// prevents accidentally sending in a number that would
167
164
// be interpretted as a start offset.
168
- return typeof encoding === 'string' ?
169
- createBuffer ( size , true ) . fill ( fill , encoding ) :
170
- createBuffer ( size , true ) . fill ( fill ) ;
165
+ if ( typeof encoding !== 'string' )
166
+ encoding = undefined ;
167
+ return createUnsafeBuffer ( size ) . fill ( fill , encoding ) ;
171
168
}
172
- return createBuffer ( size ) ;
169
+ return new FastBuffer ( size ) ;
173
170
} ;
174
171
175
172
/**
@@ -188,15 +185,15 @@ Buffer.allocUnsafe = function(size) {
188
185
**/
189
186
Buffer . allocUnsafeSlow = function ( size ) {
190
187
assertSize ( size ) ;
191
- return createBuffer ( size , true ) ;
188
+ return createUnsafeBuffer ( size ) ;
192
189
} ;
193
190
194
191
// If --zero-fill-buffers command line argument is set, a zero-filled
195
192
// buffer is returned.
196
193
function SlowBuffer ( length ) {
197
194
if ( + length != length )
198
195
length = 0 ;
199
- return createBuffer ( + length , true ) ;
196
+ return createUnsafeBuffer ( + length ) ;
200
197
}
201
198
202
199
Object . setPrototypeOf ( SlowBuffer . prototype , Uint8Array . prototype ) ;
@@ -205,7 +202,7 @@ Object.setPrototypeOf(SlowBuffer, Uint8Array);
205
202
206
203
function allocate ( size ) {
207
204
if ( size <= 0 ) {
208
- return createBuffer ( 0 ) ;
205
+ return new FastBuffer ( ) ;
209
206
}
210
207
if ( size < ( Buffer . poolSize >>> 1 ) ) {
211
208
if ( size > ( poolSize - poolOffset ) )
@@ -218,7 +215,7 @@ function allocate(size) {
218
215
// Even though this is checked above, the conditional is a safety net and
219
216
// sanity check to prevent any subsequent typed array allocation from not
220
217
// being zero filled.
221
- return createBuffer ( size , true ) ;
218
+ return createUnsafeBuffer ( size ) ;
222
219
}
223
220
}
224
221
@@ -231,7 +228,7 @@ function fromString(string, encoding) {
231
228
throw new TypeError ( '"encoding" must be a valid string encoding' ) ;
232
229
233
230
if ( string . length === 0 )
234
- return Buffer . alloc ( 0 ) ;
231
+ return new FastBuffer ( ) ;
235
232
236
233
var length = byteLength ( string , encoding ) ;
237
234
@@ -251,18 +248,30 @@ function fromArrayLike(obj) {
251
248
const length = obj . length ;
252
249
const b = allocate ( length ) ;
253
250
for ( var i = 0 ; i < length ; i ++ )
254
- b [ i ] = obj [ i ] & 255 ;
251
+ b [ i ] = obj [ i ] ;
255
252
return b ;
256
253
}
257
254
258
255
function fromArrayBuffer ( obj , byteOffset , length ) {
256
+ if ( ! isArrayBuffer ( obj ) )
257
+ throw new TypeError ( 'argument is not an ArrayBuffer' ) ;
258
+
259
259
byteOffset >>>= 0 ;
260
260
261
- if ( typeof length === 'undefined' )
262
- return binding . createFromArrayBuffer ( obj , byteOffset ) ;
261
+ const maxLength = obj . byteLength - byteOffset ;
262
+
263
+ if ( maxLength <= 0 )
264
+ throw new RangeError ( "'offset' is out of bounds" ) ;
265
+
266
+ if ( length === undefined ) {
267
+ length = maxLength ;
268
+ } else {
269
+ length >>>= 0 ;
270
+ if ( length > maxLength )
271
+ throw new RangeError ( "'length' is out of bounds" ) ;
272
+ }
263
273
264
- length >>>= 0 ;
265
- return binding . createFromArrayBuffer ( obj , byteOffset , length ) ;
274
+ return new FastBuffer ( obj , byteOffset , length ) ;
266
275
}
267
276
268
277
function fromObject ( obj ) {
@@ -279,7 +288,7 @@ function fromObject(obj) {
279
288
if ( obj ) {
280
289
if ( obj . buffer instanceof ArrayBuffer || 'length' in obj ) {
281
290
if ( typeof obj . length !== 'number' || obj . length !== obj . length ) {
282
- return allocate ( 0 ) ;
291
+ return new FastBuffer ( ) ;
283
292
}
284
293
return fromArrayLike ( obj ) ;
285
294
}
@@ -346,7 +355,7 @@ Buffer.concat = function(list, length) {
346
355
throw new TypeError ( '"list" argument must be an Array of Buffers' ) ;
347
356
348
357
if ( list . length === 0 )
349
- return Buffer . alloc ( 0 ) ;
358
+ return new FastBuffer ( ) ;
350
359
351
360
if ( length === undefined ) {
352
361
length = 0 ;
@@ -823,10 +832,26 @@ Buffer.prototype.toJSON = function() {
823
832
} ;
824
833
825
834
835
+ function adjustOffset ( offset , length ) {
836
+ offset = + offset ;
837
+ if ( offset === 0 || Number . isNaN ( offset ) ) {
838
+ return 0 ;
839
+ }
840
+ if ( offset < 0 ) {
841
+ offset += length ;
842
+ return offset > 0 ? offset : 0 ;
843
+ } else {
844
+ return offset < length ? offset : length ;
845
+ }
846
+ }
847
+
848
+
826
849
Buffer . prototype . slice = function slice ( start , end ) {
827
- const buffer = this . subarray ( start , end ) ;
828
- Object . setPrototypeOf ( buffer , Buffer . prototype ) ;
829
- return buffer ;
850
+ const srcLength = this . length ;
851
+ start = adjustOffset ( start , srcLength ) ;
852
+ end = end !== undefined ? adjustOffset ( end , srcLength ) : srcLength ;
853
+ const newLength = end > start ? end - start : 0 ;
854
+ return new FastBuffer ( this . buffer , this . byteOffset + start , newLength ) ;
830
855
} ;
831
856
832
857
0 commit comments