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 ;
@@ -62,20 +68,18 @@ Buffer.prototype.swap32 = function swap32() {
62
68
const flags = bindingObj . flags ;
63
69
const kNoZeroFill = 0 ;
64
70
65
- function createBuffer ( size , noZeroFill ) {
66
- flags [ kNoZeroFill ] = noZeroFill ? 1 : 0 ;
71
+ function createUnsafeBuffer ( size ) {
72
+ flags [ kNoZeroFill ] = 1 ;
67
73
try {
68
- const ui8 = new Uint8Array ( size ) ;
69
- Object . setPrototypeOf ( ui8 , Buffer . prototype ) ;
70
- return ui8 ;
74
+ return new FastBuffer ( size ) ;
71
75
} finally {
72
76
flags [ kNoZeroFill ] = 0 ;
73
77
}
74
78
}
75
79
76
80
function createPool ( ) {
77
81
poolSize = Buffer . poolSize ;
78
- allocPool = createBuffer ( poolSize , true ) ;
82
+ allocPool = createUnsafeBuffer ( poolSize ) ;
79
83
poolOffset = 0 ;
80
84
}
81
85
createPool ( ) ;
@@ -133,7 +137,6 @@ Buffer.from = function(value, encodingOrOffset, length) {
133
137
return fromObject ( value ) ;
134
138
} ;
135
139
136
- Object . setPrototypeOf ( Buffer . prototype , Uint8Array . prototype ) ;
137
140
Object . setPrototypeOf ( Buffer , Uint8Array ) ;
138
141
139
142
function assertSize ( size ) {
@@ -153,18 +156,16 @@ function assertSize(size) {
153
156
**/
154
157
Buffer . alloc = function ( size , fill , encoding ) {
155
158
assertSize ( size ) ;
156
- if ( size <= 0 )
157
- return createBuffer ( size ) ;
158
- if ( fill !== undefined ) {
159
+ if ( size > 0 && fill !== undefined ) {
159
160
// Since we are filling anyway, don't zero fill initially.
160
161
// Only pay attention to encoding if it's a string. This
161
162
// prevents accidentally sending in a number that would
162
163
// be interpretted as a start offset.
163
- return typeof encoding === 'string' ?
164
- createBuffer ( size , true ) . fill ( fill , encoding ) :
165
- createBuffer ( size , true ) . fill ( fill ) ;
164
+ if ( typeof encoding !== 'string' )
165
+ encoding = undefined ;
166
+ return createUnsafeBuffer ( size ) . fill ( fill , encoding ) ;
166
167
}
167
- return createBuffer ( size ) ;
168
+ return new FastBuffer ( size ) ;
168
169
} ;
169
170
170
171
/**
@@ -183,15 +184,15 @@ Buffer.allocUnsafe = function(size) {
183
184
**/
184
185
Buffer . allocUnsafeSlow = function ( size ) {
185
186
assertSize ( size ) ;
186
- return createBuffer ( size , true ) ;
187
+ return createUnsafeBuffer ( size ) ;
187
188
} ;
188
189
189
190
// If --zero-fill-buffers command line argument is set, a zero-filled
190
191
// buffer is returned.
191
192
function SlowBuffer ( length ) {
192
193
if ( + length != length )
193
194
length = 0 ;
194
- return createBuffer ( + length , true ) ;
195
+ return createUnsafeBuffer ( + length ) ;
195
196
}
196
197
197
198
Object . setPrototypeOf ( SlowBuffer . prototype , Uint8Array . prototype ) ;
@@ -200,7 +201,7 @@ Object.setPrototypeOf(SlowBuffer, Uint8Array);
200
201
201
202
function allocate ( size ) {
202
203
if ( size <= 0 ) {
203
- return createBuffer ( 0 ) ;
204
+ return new FastBuffer ( ) ;
204
205
}
205
206
if ( size < ( Buffer . poolSize >>> 1 ) ) {
206
207
if ( size > ( poolSize - poolOffset ) )
@@ -213,7 +214,7 @@ function allocate(size) {
213
214
// Even though this is checked above, the conditional is a safety net and
214
215
// sanity check to prevent any subsequent typed array allocation from not
215
216
// being zero filled.
216
- return createBuffer ( size , true ) ;
217
+ return createUnsafeBuffer ( size ) ;
217
218
}
218
219
}
219
220
@@ -226,7 +227,7 @@ function fromString(string, encoding) {
226
227
throw new TypeError ( '"encoding" must be a valid string encoding' ) ;
227
228
228
229
if ( string . length === 0 )
229
- return Buffer . alloc ( 0 ) ;
230
+ return new FastBuffer ( ) ;
230
231
231
232
var length = byteLength ( string , encoding ) ;
232
233
@@ -246,18 +247,30 @@ function fromArrayLike(obj) {
246
247
const length = obj . length ;
247
248
const b = allocate ( length ) ;
248
249
for ( var i = 0 ; i < length ; i ++ )
249
- b [ i ] = obj [ i ] & 255 ;
250
+ b [ i ] = obj [ i ] ;
250
251
return b ;
251
252
}
252
253
253
254
function fromArrayBuffer ( obj , byteOffset , length ) {
255
+ if ( ! isArrayBuffer ( obj ) )
256
+ throw new TypeError ( 'argument is not an ArrayBuffer' ) ;
257
+
254
258
byteOffset >>>= 0 ;
255
259
256
- if ( typeof length === 'undefined' )
257
- return binding . createFromArrayBuffer ( obj , byteOffset ) ;
260
+ const maxLength = obj . byteLength - byteOffset ;
261
+
262
+ if ( maxLength <= 0 )
263
+ throw new RangeError ( "'offset' is out of bounds" ) ;
264
+
265
+ if ( length === undefined ) {
266
+ length = maxLength ;
267
+ } else {
268
+ length >>>= 0 ;
269
+ if ( length > maxLength )
270
+ throw new RangeError ( "'length' is out of bounds" ) ;
271
+ }
258
272
259
- length >>>= 0 ;
260
- return binding . createFromArrayBuffer ( obj , byteOffset , length ) ;
273
+ return new FastBuffer ( obj , byteOffset , length ) ;
261
274
}
262
275
263
276
function fromObject ( obj ) {
@@ -274,7 +287,7 @@ function fromObject(obj) {
274
287
if ( obj ) {
275
288
if ( obj . buffer instanceof ArrayBuffer || 'length' in obj ) {
276
289
if ( typeof obj . length !== 'number' || obj . length !== obj . length ) {
277
- return allocate ( 0 ) ;
290
+ return new FastBuffer ( ) ;
278
291
}
279
292
return fromArrayLike ( obj ) ;
280
293
}
@@ -341,7 +354,7 @@ Buffer.concat = function(list, length) {
341
354
throw new TypeError ( '"list" argument must be an Array of Buffers' ) ;
342
355
343
356
if ( list . length === 0 )
344
- return Buffer . alloc ( 0 ) ;
357
+ return new FastBuffer ( ) ;
345
358
346
359
if ( length === undefined ) {
347
360
length = 0 ;
@@ -818,10 +831,26 @@ Buffer.prototype.toJSON = function() {
818
831
} ;
819
832
820
833
834
+ function adjustOffset ( offset , length ) {
835
+ offset = + offset ;
836
+ if ( offset === 0 || Number . isNaN ( offset ) ) {
837
+ return 0 ;
838
+ }
839
+ if ( offset < 0 ) {
840
+ offset += length ;
841
+ return offset > 0 ? offset : 0 ;
842
+ } else {
843
+ return offset < length ? offset : length ;
844
+ }
845
+ }
846
+
847
+
821
848
Buffer . prototype . slice = function slice ( start , end ) {
822
- const buffer = this . subarray ( start , end ) ;
823
- Object . setPrototypeOf ( buffer , Buffer . prototype ) ;
824
- return buffer ;
849
+ const srcLength = this . length ;
850
+ start = adjustOffset ( start , srcLength ) ;
851
+ end = end !== undefined ? adjustOffset ( end , srcLength ) : srcLength ;
852
+ const newLength = end > start ? end - start : 0 ;
853
+ return new FastBuffer ( this . buffer , this . byteOffset + start , newLength ) ;
825
854
} ;
826
855
827
856
0 commit comments