1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23 24const { 25 Array, 26 ArrayIsArray, 27 ArrayPrototypeForEach, 28 Error, 29 MathFloor, 30 MathMin, 31 MathTrunc, 32 NumberIsNaN, 33 NumberMAX_SAFE_INTEGER, 34 NumberMIN_SAFE_INTEGER, 35 ObjectCreate, 36 ObjectDefineProperties, 37 ObjectDefineProperty, 38 ObjectSetPrototypeOf, 39 StringPrototypeCharCodeAt, 40 StringPrototypeReplace, 41 StringPrototypeSlice, 42 StringPrototypeToLowerCase, 43 StringPrototypeTrim, 44 SymbolSpecies, 45 SymbolToPrimitive, 46 TypedArrayPrototypeGetByteLength, 47 TypedArrayPrototypeFill, 48 TypedArrayPrototypeSet, 49 Uint8Array, 50 Uint8ArrayPrototype, 51} = primordials; 52 53const { 54 byteLengthUtf8, 55 compare: _compare, 56 compareOffset, 57 createFromString, 58 fill: bindingFill, 59 indexOfBuffer, 60 indexOfNumber, 61 indexOfString, 62 swap16: _swap16, 63 swap32: _swap32, 64 swap64: _swap64, 65 kMaxLength, 66 kStringMaxLength, 67 zeroFill: bindingZeroFill 68} = internalBinding('buffer'); 69const { 70 getOwnNonIndexProperties, 71 propertyFilter: { 72 ALL_PROPERTIES, 73 ONLY_ENUMERABLE 74 }, 75} = internalBinding('util'); 76const { 77 customInspectSymbol, 78 isInsideNodeModules, 79 normalizeEncoding, 80 kIsEncodingSymbol 81} = require('internal/util'); 82const { 83 isAnyArrayBuffer, 84 isArrayBufferView, 85 isUint8Array 86} = require('internal/util/types'); 87const { 88 inspect: utilInspect 89} = require('internal/util/inspect'); 90const { encodings } = internalBinding('string_decoder'); 91 92const { 93 codes: { 94 ERR_BUFFER_OUT_OF_BOUNDS, 95 ERR_INVALID_ARG_TYPE, 96 ERR_INVALID_ARG_VALUE, 97 ERR_INVALID_BUFFER_SIZE, 98 ERR_INVALID_OPT_VALUE, 99 ERR_OUT_OF_RANGE, 100 ERR_UNKNOWN_ENCODING 101 }, 102 hideStackFrames 103} = require('internal/errors'); 104const { 105 validateBuffer, 106 validateInteger, 107 validateString 108} = require('internal/validators'); 109// Provide validateInteger() but with kMaxLength as the default maximum value. 110const validateOffset = (value, name, min = 0, max = kMaxLength) => 111 validateInteger(value, name, min, max); 112 113const { 114 FastBuffer, 115 markAsUntransferable, 116 addBufferPrototypeMethods 117} = require('internal/buffer'); 118 119const { 120 Blob, 121} = require('internal/blob'); 122 123FastBuffer.prototype.constructor = Buffer; 124Buffer.prototype = FastBuffer.prototype; 125addBufferPrototypeMethods(Buffer.prototype); 126 127const constants = ObjectDefineProperties({}, { 128 MAX_LENGTH: { 129 value: kMaxLength, 130 writable: false, 131 enumerable: true 132 }, 133 MAX_STRING_LENGTH: { 134 value: kStringMaxLength, 135 writable: false, 136 enumerable: true 137 } 138}); 139 140Buffer.poolSize = 8 * 1024; 141let poolSize, poolOffset, allocPool; 142 143// A toggle used to access the zero fill setting of the array buffer allocator 144// in C++. 145// |zeroFill| can be undefined when running inside an isolate where we 146// do not own the ArrayBuffer allocator. Zero fill is always on in that case. 147const zeroFill = bindingZeroFill || [0]; 148 149const encodingsMap = ObjectCreate(null); 150for (let i = 0; i < encodings.length; ++i) 151 encodingsMap[encodings[i]] = i; 152 153function createUnsafeBuffer(size) { 154 zeroFill[0] = 0; 155 try { 156 return new FastBuffer(size); 157 } finally { 158 zeroFill[0] = 1; 159 } 160} 161 162function createPool() { 163 poolSize = Buffer.poolSize; 164 allocPool = createUnsafeBuffer(poolSize).buffer; 165 markAsUntransferable(allocPool); 166 poolOffset = 0; 167} 168createPool(); 169 170function alignPool() { 171 // Ensure aligned slices 172 if (poolOffset & 0x7) { 173 poolOffset |= 0x7; 174 poolOffset++; 175 } 176} 177 178let bufferWarningAlreadyEmitted = false; 179let nodeModulesCheckCounter = 0; 180const bufferWarning = 'Buffer() is deprecated due to security and usability ' + 181 'issues. Please use the Buffer.alloc(), ' + 182 'Buffer.allocUnsafe(), or Buffer.from() methods instead.'; 183 184function showFlaggedDeprecation() { 185 if (bufferWarningAlreadyEmitted || 186 ++nodeModulesCheckCounter > 10000 || 187 (!require('internal/options').getOptionValue('--pending-deprecation') && 188 isInsideNodeModules())) { 189 // We don't emit a warning, because we either: 190 // - Already did so, or 191 // - Already checked too many times whether a call is coming 192 // from node_modules and want to stop slowing down things, or 193 // - We aren't running with `--pending-deprecation` enabled, 194 // and the code is inside `node_modules`. 195 return; 196 } 197 198 process.emitWarning(bufferWarning, 'DeprecationWarning', 'DEP0005'); 199 bufferWarningAlreadyEmitted = true; 200} 201 202function toInteger(n, defaultVal) { 203 n = +n; 204 if (!NumberIsNaN(n) && 205 n >= NumberMIN_SAFE_INTEGER && 206 n <= NumberMAX_SAFE_INTEGER) { 207 return ((n % 1) === 0 ? n : MathFloor(n)); 208 } 209 return defaultVal; 210} 211 212function _copy(source, target, targetStart, sourceStart, sourceEnd) { 213 if (!isUint8Array(source)) 214 throw new ERR_INVALID_ARG_TYPE('source', ['Buffer', 'Uint8Array'], source); 215 if (!isUint8Array(target)) 216 throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); 217 218 if (targetStart === undefined) { 219 targetStart = 0; 220 } else { 221 targetStart = toInteger(targetStart, 0); 222 if (targetStart < 0) 223 throw new ERR_OUT_OF_RANGE('targetStart', '>= 0', targetStart); 224 } 225 226 if (sourceStart === undefined) { 227 sourceStart = 0; 228 } else { 229 sourceStart = toInteger(sourceStart, 0); 230 if (sourceStart < 0) 231 throw new ERR_OUT_OF_RANGE('sourceStart', '>= 0', sourceStart); 232 } 233 234 if (sourceEnd === undefined) { 235 sourceEnd = source.length; 236 } else { 237 sourceEnd = toInteger(sourceEnd, 0); 238 if (sourceEnd < 0) 239 throw new ERR_OUT_OF_RANGE('sourceEnd', '>= 0', sourceEnd); 240 } 241 242 if (targetStart >= target.length || sourceStart >= sourceEnd) 243 return 0; 244 245 if (sourceStart > source.length) { 246 throw new ERR_OUT_OF_RANGE('sourceStart', 247 `<= ${source.length}`, 248 sourceStart); 249 } 250 251 return _copyActual(source, target, targetStart, sourceStart, sourceEnd); 252} 253 254function _copyActual(source, target, targetStart, sourceStart, sourceEnd) { 255 if (sourceEnd - sourceStart > target.length - targetStart) 256 sourceEnd = sourceStart + target.length - targetStart; 257 258 let nb = sourceEnd - sourceStart; 259 const sourceLen = source.length - sourceStart; 260 if (nb > sourceLen) 261 nb = sourceLen; 262 263 if (sourceStart !== 0 || sourceEnd < source.length) 264 source = new Uint8Array(source.buffer, source.byteOffset + sourceStart, nb); 265 266 TypedArrayPrototypeSet(target, source, targetStart); 267 268 return nb; 269} 270 271/** 272 * The Buffer() constructor is deprecated in documentation and should not be 273 * used moving forward. Rather, developers should use one of the three new 274 * factory APIs: Buffer.from(), Buffer.allocUnsafe() or Buffer.alloc() based on 275 * their specific needs. There is no runtime deprecation because of the extent 276 * to which the Buffer constructor is used in the ecosystem currently -- a 277 * runtime deprecation would introduce too much breakage at this time. It's not 278 * likely that the Buffer constructors would ever actually be removed. 279 * Deprecation Code: DEP0005 280 */ 281function Buffer(arg, encodingOrOffset, length) { 282 showFlaggedDeprecation(); 283 // Common case. 284 if (typeof arg === 'number') { 285 if (typeof encodingOrOffset === 'string') { 286 throw new ERR_INVALID_ARG_TYPE('string', 'string', arg); 287 } 288 return Buffer.alloc(arg); 289 } 290 return Buffer.from(arg, encodingOrOffset, length); 291} 292 293ObjectDefineProperty(Buffer, SymbolSpecies, { 294 enumerable: false, 295 configurable: true, 296 get() { return FastBuffer; } 297}); 298 299/** 300 * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError 301 * if value is a number. 302 * Buffer.from(str[, encoding]) 303 * Buffer.from(array) 304 * Buffer.from(buffer) 305 * Buffer.from(arrayBuffer[, byteOffset[, length]]) 306 */ 307Buffer.from = function from(value, encodingOrOffset, length) { 308 if (typeof value === 'string') 309 return fromString(value, encodingOrOffset); 310 311 if (typeof value === 'object' && value !== null) { 312 if (isAnyArrayBuffer(value)) 313 return fromArrayBuffer(value, encodingOrOffset, length); 314 315 const valueOf = value.valueOf && value.valueOf(); 316 if (valueOf != null && 317 valueOf !== value && 318 (typeof valueOf === 'string' || typeof valueOf === 'object')) { 319 return from(valueOf, encodingOrOffset, length); 320 } 321 322 const b = fromObject(value); 323 if (b) 324 return b; 325 326 if (typeof value[SymbolToPrimitive] === 'function') { 327 const primitive = value[SymbolToPrimitive]('string'); 328 if (typeof primitive === 'string') { 329 return fromString(primitive, encodingOrOffset); 330 } 331 } 332 } 333 334 throw new ERR_INVALID_ARG_TYPE( 335 'first argument', 336 ['string', 'Buffer', 'ArrayBuffer', 'Array', 'Array-like Object'], 337 value 338 ); 339}; 340 341// Identical to the built-in %TypedArray%.of(), but avoids using the deprecated 342// Buffer() constructor. Must use arrow function syntax to avoid automatically 343// adding a `prototype` property and making the function a constructor. 344// 345// Refs: https://tc39.github.io/ecma262/#sec-%typedarray%.of 346// Refs: https://esdiscuss.org/topic/isconstructor#content-11 347const of = (...items) => { 348 const newObj = createUnsafeBuffer(items.length); 349 for (let k = 0; k < items.length; k++) 350 newObj[k] = items[k]; 351 return newObj; 352}; 353Buffer.of = of; 354 355ObjectSetPrototypeOf(Buffer, Uint8Array); 356 357// The 'assertSize' method will remove itself from the callstack when an error 358// occurs. This is done simply to keep the internal details of the 359// implementation from bleeding out to users. 360const assertSize = hideStackFrames((size) => { 361 if (typeof size !== 'number') { 362 throw new ERR_INVALID_ARG_TYPE('size', 'number', size); 363 } 364 if (!(size >= 0 && size <= kMaxLength)) { 365 throw new ERR_INVALID_OPT_VALUE.RangeError('size', size); 366 } 367}); 368 369/** 370 * Creates a new filled Buffer instance. 371 * alloc(size[, fill[, encoding]]) 372 */ 373Buffer.alloc = function alloc(size, fill, encoding) { 374 assertSize(size); 375 if (fill !== undefined && fill !== 0 && size > 0) { 376 const buf = createUnsafeBuffer(size); 377 return _fill(buf, fill, 0, buf.length, encoding); 378 } 379 return new FastBuffer(size); 380}; 381 382/** 383 * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer 384 * instance. If `--zero-fill-buffers` is set, will zero-fill the buffer. 385 */ 386Buffer.allocUnsafe = function allocUnsafe(size) { 387 assertSize(size); 388 return allocate(size); 389}; 390 391/** 392 * Equivalent to SlowBuffer(num), by default creates a non-zero-filled 393 * Buffer instance that is not allocated off the pre-initialized pool. 394 * If `--zero-fill-buffers` is set, will zero-fill the buffer. 395 */ 396Buffer.allocUnsafeSlow = function allocUnsafeSlow(size) { 397 assertSize(size); 398 return createUnsafeBuffer(size); 399}; 400 401// If --zero-fill-buffers command line argument is set, a zero-filled 402// buffer is returned. 403function SlowBuffer(length) { 404 assertSize(length); 405 return createUnsafeBuffer(length); 406} 407 408ObjectSetPrototypeOf(SlowBuffer.prototype, Uint8ArrayPrototype); 409ObjectSetPrototypeOf(SlowBuffer, Uint8Array); 410 411function allocate(size) { 412 if (size <= 0) { 413 return new FastBuffer(); 414 } 415 if (size < (Buffer.poolSize >>> 1)) { 416 if (size > (poolSize - poolOffset)) 417 createPool(); 418 const b = new FastBuffer(allocPool, poolOffset, size); 419 poolOffset += size; 420 alignPool(); 421 return b; 422 } 423 return createUnsafeBuffer(size); 424} 425 426function fromStringFast(string, ops) { 427 const length = ops.byteLength(string); 428 429 if (length >= (Buffer.poolSize >>> 1)) 430 return createFromString(string, ops.encodingVal); 431 432 if (length > (poolSize - poolOffset)) 433 createPool(); 434 let b = new FastBuffer(allocPool, poolOffset, length); 435 const actual = ops.write(b, string, 0, length); 436 if (actual !== length) { 437 // byteLength() may overestimate. That's a rare case, though. 438 b = new FastBuffer(allocPool, poolOffset, actual); 439 } 440 poolOffset += actual; 441 alignPool(); 442 return b; 443} 444 445function fromString(string, encoding) { 446 let ops; 447 if (typeof encoding !== 'string' || encoding.length === 0) { 448 if (string.length === 0) 449 return new FastBuffer(); 450 ops = encodingOps.utf8; 451 encoding = undefined; 452 } else { 453 ops = getEncodingOps(encoding); 454 if (ops === undefined) 455 throw new ERR_UNKNOWN_ENCODING(encoding); 456 if (string.length === 0) 457 return new FastBuffer(); 458 } 459 return fromStringFast(string, ops); 460} 461 462function fromArrayBuffer(obj, byteOffset, length) { 463 // Convert byteOffset to integer 464 if (byteOffset === undefined) { 465 byteOffset = 0; 466 } else { 467 byteOffset = +byteOffset; 468 if (NumberIsNaN(byteOffset)) 469 byteOffset = 0; 470 } 471 472 const maxLength = obj.byteLength - byteOffset; 473 474 if (maxLength < 0) 475 throw new ERR_BUFFER_OUT_OF_BOUNDS('offset'); 476 477 if (length === undefined) { 478 length = maxLength; 479 } else { 480 // Convert length to non-negative integer. 481 length = +length; 482 if (length > 0) { 483 if (length > maxLength) 484 throw new ERR_BUFFER_OUT_OF_BOUNDS('length'); 485 } else { 486 length = 0; 487 } 488 } 489 490 return new FastBuffer(obj, byteOffset, length); 491} 492 493function fromArrayLike(obj) { 494 if (obj.length <= 0) 495 return new FastBuffer(); 496 if (obj.length < (Buffer.poolSize >>> 1)) { 497 if (obj.length > (poolSize - poolOffset)) 498 createPool(); 499 const b = new FastBuffer(allocPool, poolOffset, obj.length); 500 TypedArrayPrototypeSet(b, obj, 0); 501 poolOffset += obj.length; 502 alignPool(); 503 return b; 504 } 505 return new FastBuffer(obj); 506} 507 508function fromObject(obj) { 509 if (obj.length !== undefined || isAnyArrayBuffer(obj.buffer)) { 510 if (typeof obj.length !== 'number') { 511 return new FastBuffer(); 512 } 513 return fromArrayLike(obj); 514 } 515 516 if (obj.type === 'Buffer' && ArrayIsArray(obj.data)) { 517 return fromArrayLike(obj.data); 518 } 519} 520 521// Static methods 522 523Buffer.isBuffer = function isBuffer(b) { 524 return b instanceof Buffer; 525}; 526 527Buffer.compare = function compare(buf1, buf2) { 528 if (!isUint8Array(buf1)) { 529 throw new ERR_INVALID_ARG_TYPE('buf1', ['Buffer', 'Uint8Array'], buf1); 530 } 531 532 if (!isUint8Array(buf2)) { 533 throw new ERR_INVALID_ARG_TYPE('buf2', ['Buffer', 'Uint8Array'], buf2); 534 } 535 536 if (buf1 === buf2) { 537 return 0; 538 } 539 540 return _compare(buf1, buf2); 541}; 542 543Buffer.isEncoding = function isEncoding(encoding) { 544 return typeof encoding === 'string' && encoding.length !== 0 && 545 normalizeEncoding(encoding) !== undefined; 546}; 547Buffer[kIsEncodingSymbol] = Buffer.isEncoding; 548 549Buffer.concat = function concat(list, length) { 550 if (!ArrayIsArray(list)) { 551 throw new ERR_INVALID_ARG_TYPE('list', 'Array', list); 552 } 553 554 if (list.length === 0) 555 return new FastBuffer(); 556 557 if (length === undefined) { 558 length = 0; 559 for (let i = 0; i < list.length; i++) { 560 if (list[i].length) { 561 length += list[i].length; 562 } 563 } 564 } else { 565 validateOffset(length, 'length'); 566 } 567 568 const buffer = Buffer.allocUnsafe(length); 569 let pos = 0; 570 for (let i = 0; i < list.length; i++) { 571 const buf = list[i]; 572 if (!isUint8Array(buf)) { 573 // TODO(BridgeAR): This should not be of type ERR_INVALID_ARG_TYPE. 574 // Instead, find the proper error code for this. 575 throw new ERR_INVALID_ARG_TYPE( 576 `list[${i}]`, ['Buffer', 'Uint8Array'], list[i]); 577 } 578 pos += _copyActual(buf, buffer, pos, 0, buf.length); 579 } 580 581 // Note: `length` is always equal to `buffer.length` at this point 582 if (pos < length) { 583 // Zero-fill the remaining bytes if the specified `length` was more than 584 // the actual total length, i.e. if we have some remaining allocated bytes 585 // there were not initialized. 586 TypedArrayPrototypeFill(buffer, 0, pos, length); 587 } 588 589 return buffer; 590}; 591 592function base64ByteLength(str, bytes) { 593 // Handle padding 594 if (StringPrototypeCharCodeAt(str, bytes - 1) === 0x3D) 595 bytes--; 596 if (bytes > 1 && StringPrototypeCharCodeAt(str, bytes - 1) === 0x3D) 597 bytes--; 598 599 // Base64 ratio: 3/4 600 return (bytes * 3) >>> 2; 601} 602 603const encodingOps = { 604 utf8: { 605 encoding: 'utf8', 606 encodingVal: encodingsMap.utf8, 607 byteLength: byteLengthUtf8, 608 write: (buf, string, offset, len) => buf.utf8Write(string, offset, len), 609 slice: (buf, start, end) => buf.utf8Slice(start, end), 610 indexOf: (buf, val, byteOffset, dir) => 611 indexOfString(buf, val, byteOffset, encodingsMap.utf8, dir) 612 }, 613 ucs2: { 614 encoding: 'ucs2', 615 encodingVal: encodingsMap.utf16le, 616 byteLength: (string) => string.length * 2, 617 write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 618 slice: (buf, start, end) => buf.ucs2Slice(start, end), 619 indexOf: (buf, val, byteOffset, dir) => 620 indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 621 }, 622 utf16le: { 623 encoding: 'utf16le', 624 encodingVal: encodingsMap.utf16le, 625 byteLength: (string) => string.length * 2, 626 write: (buf, string, offset, len) => buf.ucs2Write(string, offset, len), 627 slice: (buf, start, end) => buf.ucs2Slice(start, end), 628 indexOf: (buf, val, byteOffset, dir) => 629 indexOfString(buf, val, byteOffset, encodingsMap.utf16le, dir) 630 }, 631 latin1: { 632 encoding: 'latin1', 633 encodingVal: encodingsMap.latin1, 634 byteLength: (string) => string.length, 635 write: (buf, string, offset, len) => buf.latin1Write(string, offset, len), 636 slice: (buf, start, end) => buf.latin1Slice(start, end), 637 indexOf: (buf, val, byteOffset, dir) => 638 indexOfString(buf, val, byteOffset, encodingsMap.latin1, dir) 639 }, 640 ascii: { 641 encoding: 'ascii', 642 encodingVal: encodingsMap.ascii, 643 byteLength: (string) => string.length, 644 write: (buf, string, offset, len) => buf.asciiWrite(string, offset, len), 645 slice: (buf, start, end) => buf.asciiSlice(start, end), 646 indexOf: (buf, val, byteOffset, dir) => 647 indexOfBuffer(buf, 648 fromStringFast(val, encodingOps.ascii), 649 byteOffset, 650 encodingsMap.ascii, 651 dir) 652 }, 653 base64: { 654 encoding: 'base64', 655 encodingVal: encodingsMap.base64, 656 byteLength: (string) => base64ByteLength(string, string.length), 657 write: (buf, string, offset, len) => buf.base64Write(string, offset, len), 658 slice: (buf, start, end) => buf.base64Slice(start, end), 659 indexOf: (buf, val, byteOffset, dir) => 660 indexOfBuffer(buf, 661 fromStringFast(val, encodingOps.base64), 662 byteOffset, 663 encodingsMap.base64, 664 dir) 665 }, 666 base64url: { 667 encoding: 'base64url', 668 encodingVal: encodingsMap.base64url, 669 byteLength: (string) => base64ByteLength(string, string.length), 670 write: (buf, string, offset, len) => 671 buf.base64urlWrite(string, offset, len), 672 slice: (buf, start, end) => buf.base64urlSlice(start, end), 673 indexOf: (buf, val, byteOffset, dir) => 674 indexOfBuffer(buf, 675 fromStringFast(val, encodingOps.base64url), 676 byteOffset, 677 encodingsMap.base64url, 678 dir) 679 }, 680 hex: { 681 encoding: 'hex', 682 encodingVal: encodingsMap.hex, 683 byteLength: (string) => string.length >>> 1, 684 write: (buf, string, offset, len) => buf.hexWrite(string, offset, len), 685 slice: (buf, start, end) => buf.hexSlice(start, end), 686 indexOf: (buf, val, byteOffset, dir) => 687 indexOfBuffer(buf, 688 fromStringFast(val, encodingOps.hex), 689 byteOffset, 690 encodingsMap.hex, 691 dir) 692 } 693}; 694function getEncodingOps(encoding) { 695 encoding += ''; 696 switch (encoding.length) { 697 case 4: 698 if (encoding === 'utf8') return encodingOps.utf8; 699 if (encoding === 'ucs2') return encodingOps.ucs2; 700 encoding = StringPrototypeToLowerCase(encoding); 701 if (encoding === 'utf8') return encodingOps.utf8; 702 if (encoding === 'ucs2') return encodingOps.ucs2; 703 break; 704 case 5: 705 if (encoding === 'utf-8') return encodingOps.utf8; 706 if (encoding === 'ascii') return encodingOps.ascii; 707 if (encoding === 'ucs-2') return encodingOps.ucs2; 708 encoding = StringPrototypeToLowerCase(encoding); 709 if (encoding === 'utf-8') return encodingOps.utf8; 710 if (encoding === 'ascii') return encodingOps.ascii; 711 if (encoding === 'ucs-2') return encodingOps.ucs2; 712 break; 713 case 7: 714 if (encoding === 'utf16le' || 715 StringPrototypeToLowerCase(encoding) === 'utf16le') 716 return encodingOps.utf16le; 717 break; 718 case 8: 719 if (encoding === 'utf-16le' || 720 StringPrototypeToLowerCase(encoding) === 'utf-16le') 721 return encodingOps.utf16le; 722 break; 723 case 6: 724 if (encoding === 'latin1' || encoding === 'binary') 725 return encodingOps.latin1; 726 if (encoding === 'base64') return encodingOps.base64; 727 encoding = StringPrototypeToLowerCase(encoding); 728 if (encoding === 'latin1' || encoding === 'binary') 729 return encodingOps.latin1; 730 if (encoding === 'base64') return encodingOps.base64; 731 break; 732 case 3: 733 if (encoding === 'hex' || StringPrototypeToLowerCase(encoding) === 'hex') 734 return encodingOps.hex; 735 break; 736 case 9: 737 if (encoding === 'base64url' || 738 StringPrototypeToLowerCase(encoding) === 'base64url') 739 return encodingOps.base64url; 740 break; 741 } 742} 743 744function byteLength(string, encoding) { 745 if (typeof string !== 'string') { 746 if (isArrayBufferView(string) || isAnyArrayBuffer(string)) { 747 return string.byteLength; 748 } 749 750 throw new ERR_INVALID_ARG_TYPE( 751 'string', ['string', 'Buffer', 'ArrayBuffer'], string 752 ); 753 } 754 755 const len = string.length; 756 const mustMatch = (arguments.length > 2 && arguments[2] === true); 757 if (!mustMatch && len === 0) 758 return 0; 759 760 if (!encoding) 761 return (mustMatch ? -1 : byteLengthUtf8(string)); 762 763 const ops = getEncodingOps(encoding); 764 if (ops === undefined) 765 return (mustMatch ? -1 : byteLengthUtf8(string)); 766 return ops.byteLength(string); 767} 768 769Buffer.byteLength = byteLength; 770 771// For backwards compatibility. 772ObjectDefineProperty(Buffer.prototype, 'parent', { 773 enumerable: true, 774 get() { 775 if (!(this instanceof Buffer)) 776 return undefined; 777 return this.buffer; 778 } 779}); 780ObjectDefineProperty(Buffer.prototype, 'offset', { 781 enumerable: true, 782 get() { 783 if (!(this instanceof Buffer)) 784 return undefined; 785 return this.byteOffset; 786 } 787}); 788 789Buffer.prototype.copy = 790 function copy(target, targetStart, sourceStart, sourceEnd) { 791 return _copy(this, target, targetStart, sourceStart, sourceEnd); 792 }; 793 794// No need to verify that "buf.length <= MAX_UINT32" since it's a read-only 795// property of a typed array. 796// This behaves neither like String nor Uint8Array in that we set start/end 797// to their upper/lower bounds if the value passed is out of range. 798Buffer.prototype.toString = function toString(encoding, start, end) { 799 if (arguments.length === 0) { 800 return this.utf8Slice(0, this.length); 801 } 802 803 const len = this.length; 804 805 if (start <= 0) 806 start = 0; 807 else if (start >= len) 808 return ''; 809 else 810 start |= 0; 811 812 if (end === undefined || end > len) 813 end = len; 814 else 815 end |= 0; 816 817 if (end <= start) 818 return ''; 819 820 if (encoding === undefined) 821 return this.utf8Slice(start, end); 822 823 const ops = getEncodingOps(encoding); 824 if (ops === undefined) 825 throw new ERR_UNKNOWN_ENCODING(encoding); 826 827 return ops.slice(this, start, end); 828}; 829 830Buffer.prototype.equals = function equals(otherBuffer) { 831 if (!isUint8Array(otherBuffer)) { 832 throw new ERR_INVALID_ARG_TYPE( 833 'otherBuffer', ['Buffer', 'Uint8Array'], otherBuffer); 834 } 835 836 if (this === otherBuffer) 837 return true; 838 839 if (this.byteLength !== otherBuffer.byteLength) 840 return false; 841 842 return this.byteLength === 0 || _compare(this, otherBuffer) === 0; 843}; 844 845let INSPECT_MAX_BYTES = 50; 846// Override how buffers are presented by util.inspect(). 847Buffer.prototype[customInspectSymbol] = function inspect(recurseTimes, ctx) { 848 const max = INSPECT_MAX_BYTES; 849 const actualMax = MathMin(max, this.length); 850 const remaining = this.length - max; 851 let str = StringPrototypeTrim(StringPrototypeReplace( 852 this.hexSlice(0, actualMax), /(.{2})/g, '$1 ')); 853 if (remaining > 0) 854 str += ` ... ${remaining} more byte${remaining > 1 ? 's' : ''}`; 855 // Inspect special properties as well, if possible. 856 if (ctx) { 857 let extras = false; 858 const filter = ctx.showHidden ? ALL_PROPERTIES : ONLY_ENUMERABLE; 859 const obj = ObjectCreate(null); 860 ArrayPrototypeForEach(getOwnNonIndexProperties(this, filter), 861 (key) => { 862 extras = true; 863 obj[key] = this[key]; 864 }); 865 if (extras) { 866 if (this.length !== 0) 867 str += ', '; 868 // '[Object: null prototype] {'.length === 26 869 // This is guarded with a test. 870 str += StringPrototypeSlice(utilInspect(obj, { 871 ...ctx, 872 breakLength: Infinity, 873 compact: true 874 }), 27, -2); 875 } 876 } 877 return `<${this.constructor.name} ${str}>`; 878}; 879Buffer.prototype.inspect = Buffer.prototype[customInspectSymbol]; 880 881Buffer.prototype.compare = function compare(target, 882 targetStart, 883 targetEnd, 884 sourceStart, 885 sourceEnd) { 886 if (!isUint8Array(target)) { 887 throw new ERR_INVALID_ARG_TYPE('target', ['Buffer', 'Uint8Array'], target); 888 } 889 if (arguments.length === 1) 890 return _compare(this, target); 891 892 if (targetStart === undefined) 893 targetStart = 0; 894 else 895 validateOffset(targetStart, 'targetStart'); 896 897 if (targetEnd === undefined) 898 targetEnd = target.length; 899 else 900 validateOffset(targetEnd, 'targetEnd', 0, target.length); 901 902 if (sourceStart === undefined) 903 sourceStart = 0; 904 else 905 validateOffset(sourceStart, 'sourceStart'); 906 907 if (sourceEnd === undefined) 908 sourceEnd = this.length; 909 else 910 validateOffset(sourceEnd, 'sourceEnd', 0, this.length); 911 912 if (sourceStart >= sourceEnd) 913 return (targetStart >= targetEnd ? 0 : -1); 914 if (targetStart >= targetEnd) 915 return 1; 916 917 return compareOffset(this, target, targetStart, sourceStart, targetEnd, 918 sourceEnd); 919}; 920 921// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, 922// OR the last index of `val` in `buffer` at offset <= `byteOffset`. 923// 924// Arguments: 925// - buffer - a Buffer to search 926// - val - a string, Buffer, or number 927// - byteOffset - an index into `buffer`; will be clamped to an int32 928// - encoding - an optional encoding, relevant if val is a string 929// - dir - true for indexOf, false for lastIndexOf 930function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { 931 validateBuffer(buffer); 932 933 if (typeof byteOffset === 'string') { 934 encoding = byteOffset; 935 byteOffset = undefined; 936 } else if (byteOffset > 0x7fffffff) { 937 byteOffset = 0x7fffffff; 938 } else if (byteOffset < -0x80000000) { 939 byteOffset = -0x80000000; 940 } 941 // Coerce to Number. Values like null and [] become 0. 942 byteOffset = +byteOffset; 943 // If the offset is undefined, "foo", {}, coerces to NaN, search whole buffer. 944 if (NumberIsNaN(byteOffset)) { 945 byteOffset = dir ? 0 : (buffer.length || buffer.byteLength); 946 } 947 dir = !!dir; // Cast to bool. 948 949 if (typeof val === 'number') 950 return indexOfNumber(buffer, val >>> 0, byteOffset, dir); 951 952 let ops; 953 if (encoding === undefined) 954 ops = encodingOps.utf8; 955 else 956 ops = getEncodingOps(encoding); 957 958 if (typeof val === 'string') { 959 if (ops === undefined) 960 throw new ERR_UNKNOWN_ENCODING(encoding); 961 return ops.indexOf(buffer, val, byteOffset, dir); 962 } 963 964 if (isUint8Array(val)) { 965 const encodingVal = 966 (ops === undefined ? encodingsMap.utf8 : ops.encodingVal); 967 return indexOfBuffer(buffer, val, byteOffset, encodingVal, dir); 968 } 969 970 throw new ERR_INVALID_ARG_TYPE( 971 'value', ['number', 'string', 'Buffer', 'Uint8Array'], val 972 ); 973} 974 975Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { 976 return bidirectionalIndexOf(this, val, byteOffset, encoding, true); 977}; 978 979Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { 980 return bidirectionalIndexOf(this, val, byteOffset, encoding, false); 981}; 982 983Buffer.prototype.includes = function includes(val, byteOffset, encoding) { 984 return this.indexOf(val, byteOffset, encoding) !== -1; 985}; 986 987// Usage: 988// buffer.fill(number[, offset[, end]]) 989// buffer.fill(buffer[, offset[, end]]) 990// buffer.fill(string[, offset[, end]][, encoding]) 991Buffer.prototype.fill = function fill(value, offset, end, encoding) { 992 return _fill(this, value, offset, end, encoding); 993}; 994 995function _fill(buf, value, offset, end, encoding) { 996 if (typeof value === 'string') { 997 if (offset === undefined || typeof offset === 'string') { 998 encoding = offset; 999 offset = 0; 1000 end = buf.length; 1001 } else if (typeof end === 'string') { 1002 encoding = end; 1003 end = buf.length; 1004 } 1005 1006 const normalizedEncoding = normalizeEncoding(encoding); 1007 if (normalizedEncoding === undefined) { 1008 validateString(encoding, 'encoding'); 1009 throw new ERR_UNKNOWN_ENCODING(encoding); 1010 } 1011 1012 if (value.length === 0) { 1013 // If value === '' default to zero. 1014 value = 0; 1015 } else if (value.length === 1) { 1016 // Fast path: If `value` fits into a single byte, use that numeric value. 1017 if (normalizedEncoding === 'utf8') { 1018 const code = StringPrototypeCharCodeAt(value, 0); 1019 if (code < 128) { 1020 value = code; 1021 } 1022 } else if (normalizedEncoding === 'latin1') { 1023 value = StringPrototypeCharCodeAt(value, 0); 1024 } 1025 } 1026 } else { 1027 encoding = undefined; 1028 } 1029 1030 if (offset === undefined) { 1031 offset = 0; 1032 end = buf.length; 1033 } else { 1034 validateOffset(offset, 'offset'); 1035 // Invalid ranges are not set to a default, so can range check early. 1036 if (end === undefined) { 1037 end = buf.length; 1038 } else { 1039 validateOffset(end, 'end', 0, buf.length); 1040 } 1041 if (offset >= end) 1042 return buf; 1043 } 1044 1045 1046 if (typeof value === 'number') { 1047 // OOB check 1048 const byteLen = TypedArrayPrototypeGetByteLength(buf); 1049 const fillLength = end - offset; 1050 if (offset > end || fillLength + offset > byteLen) 1051 throw new ERR_BUFFER_OUT_OF_BOUNDS(); 1052 1053 TypedArrayPrototypeFill(buf, value, offset, end); 1054 } else { 1055 const res = bindingFill(buf, value, offset, end, encoding); 1056 if (res < 0) { 1057 if (res === -1) 1058 throw new ERR_INVALID_ARG_VALUE('value', value); 1059 throw new ERR_BUFFER_OUT_OF_BOUNDS(); 1060 } 1061 } 1062 1063 return buf; 1064} 1065 1066Buffer.prototype.write = function write(string, offset, length, encoding) { 1067 // Buffer#write(string); 1068 if (offset === undefined) { 1069 return this.utf8Write(string, 0, this.length); 1070 } 1071 // Buffer#write(string, encoding) 1072 if (length === undefined && typeof offset === 'string') { 1073 encoding = offset; 1074 length = this.length; 1075 offset = 0; 1076 1077 // Buffer#write(string, offset[, length][, encoding]) 1078 } else { 1079 validateOffset(offset, 'offset', 0, this.length); 1080 1081 const remaining = this.length - offset; 1082 1083 if (length === undefined) { 1084 length = remaining; 1085 } else if (typeof length === 'string') { 1086 encoding = length; 1087 length = remaining; 1088 } else { 1089 validateOffset(length, 'length', 0, this.length); 1090 if (length > remaining) 1091 length = remaining; 1092 } 1093 } 1094 1095 if (!encoding) 1096 return this.utf8Write(string, offset, length); 1097 1098 const ops = getEncodingOps(encoding); 1099 if (ops === undefined) 1100 throw new ERR_UNKNOWN_ENCODING(encoding); 1101 return ops.write(this, string, offset, length); 1102}; 1103 1104Buffer.prototype.toJSON = function toJSON() { 1105 if (this.length > 0) { 1106 const data = new Array(this.length); 1107 for (let i = 0; i < this.length; ++i) 1108 data[i] = this[i]; 1109 return { type: 'Buffer', data }; 1110 } 1111 return { type: 'Buffer', data: [] }; 1112}; 1113 1114function adjustOffset(offset, length) { 1115 // Use Math.trunc() to convert offset to an integer value that can be larger 1116 // than an Int32. Hence, don't use offset | 0 or similar techniques. 1117 offset = MathTrunc(offset); 1118 if (offset === 0) { 1119 return 0; 1120 } 1121 if (offset < 0) { 1122 offset += length; 1123 return offset > 0 ? offset : 0; 1124 } 1125 if (offset < length) { 1126 return offset; 1127 } 1128 return NumberIsNaN(offset) ? 0 : length; 1129} 1130 1131Buffer.prototype.slice = function slice(start, end) { 1132 const srcLength = this.length; 1133 start = adjustOffset(start, srcLength); 1134 end = end !== undefined ? adjustOffset(end, srcLength) : srcLength; 1135 const newLength = end > start ? end - start : 0; 1136 return new FastBuffer(this.buffer, this.byteOffset + start, newLength); 1137}; 1138 1139function swap(b, n, m) { 1140 const i = b[n]; 1141 b[n] = b[m]; 1142 b[m] = i; 1143} 1144 1145Buffer.prototype.swap16 = function swap16() { 1146 // For Buffer.length < 128, it's generally faster to 1147 // do the swap in javascript. For larger buffers, 1148 // dropping down to the native code is faster. 1149 const len = this.length; 1150 if (len % 2 !== 0) 1151 throw new ERR_INVALID_BUFFER_SIZE('16-bits'); 1152 if (len < 128) { 1153 for (let i = 0; i < len; i += 2) 1154 swap(this, i, i + 1); 1155 return this; 1156 } 1157 return _swap16(this); 1158}; 1159 1160Buffer.prototype.swap32 = function swap32() { 1161 // For Buffer.length < 192, it's generally faster to 1162 // do the swap in javascript. For larger buffers, 1163 // dropping down to the native code is faster. 1164 const len = this.length; 1165 if (len % 4 !== 0) 1166 throw new ERR_INVALID_BUFFER_SIZE('32-bits'); 1167 if (len < 192) { 1168 for (let i = 0; i < len; i += 4) { 1169 swap(this, i, i + 3); 1170 swap(this, i + 1, i + 2); 1171 } 1172 return this; 1173 } 1174 return _swap32(this); 1175}; 1176 1177Buffer.prototype.swap64 = function swap64() { 1178 // For Buffer.length < 192, it's generally faster to 1179 // do the swap in javascript. For larger buffers, 1180 // dropping down to the native code is faster. 1181 const len = this.length; 1182 if (len % 8 !== 0) 1183 throw new ERR_INVALID_BUFFER_SIZE('64-bits'); 1184 if (len < 192) { 1185 for (let i = 0; i < len; i += 8) { 1186 swap(this, i, i + 7); 1187 swap(this, i + 1, i + 6); 1188 swap(this, i + 2, i + 5); 1189 swap(this, i + 3, i + 4); 1190 } 1191 return this; 1192 } 1193 return _swap64(this); 1194}; 1195 1196Buffer.prototype.toLocaleString = Buffer.prototype.toString; 1197 1198let transcode; 1199if (internalBinding('config').hasIntl) { 1200 const { 1201 icuErrName, 1202 transcode: _transcode 1203 } = internalBinding('icu'); 1204 1205 // Transcodes the Buffer from one encoding to another, returning a new 1206 // Buffer instance. 1207 transcode = function transcode(source, fromEncoding, toEncoding) { 1208 if (!isUint8Array(source)) { 1209 throw new ERR_INVALID_ARG_TYPE('source', 1210 ['Buffer', 'Uint8Array'], source); 1211 } 1212 if (source.length === 0) return Buffer.alloc(0); 1213 1214 fromEncoding = normalizeEncoding(fromEncoding) || fromEncoding; 1215 toEncoding = normalizeEncoding(toEncoding) || toEncoding; 1216 const result = _transcode(source, fromEncoding, toEncoding); 1217 if (typeof result !== 'number') 1218 return result; 1219 1220 const code = icuErrName(result); 1221 // eslint-disable-next-line no-restricted-syntax 1222 const err = new Error(`Unable to transcode Buffer [${code}]`); 1223 err.code = code; 1224 err.errno = result; 1225 throw err; 1226 }; 1227} 1228 1229let DOMException; 1230 1231const lazyInvalidCharError = hideStackFrames((message, name) => { 1232 if (DOMException === undefined) 1233 DOMException = internalBinding('messaging').DOMException; 1234 throw new DOMException('Invalid character', 'InvalidCharacterError'); 1235}); 1236 1237function btoa(input) { 1238 // The implementation here has not been performance optimized in any way and 1239 // should not be. 1240 // Refs: https://github.com/nodejs/node/pull/38433#issuecomment-828426932 1241 input = `${input}`; 1242 for (let n = 0; n < input.length; n++) { 1243 if (input[n].charCodeAt(0) > 0xff) 1244 lazyInvalidCharError(); 1245 } 1246 const buf = Buffer.from(input, 'latin1'); 1247 return buf.toString('base64'); 1248} 1249 1250const kBase64Digits = 1251 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; 1252 1253function atob(input) { 1254 // The implementation here has not been performance optimized in any way and 1255 // should not be. 1256 // Refs: https://github.com/nodejs/node/pull/38433#issuecomment-828426932 1257 input = `${input}`; 1258 for (let n = 0; n < input.length; n++) { 1259 if (!kBase64Digits.includes(input[n])) 1260 lazyInvalidCharError(); 1261 } 1262 return Buffer.from(input, 'base64').toString('latin1'); 1263} 1264 1265module.exports = { 1266 Blob, 1267 Buffer, 1268 SlowBuffer, 1269 transcode, 1270 // Legacy 1271 kMaxLength, 1272 kStringMaxLength, 1273 btoa, 1274 atob, 1275}; 1276 1277ObjectDefineProperties(module.exports, { 1278 constants: { 1279 configurable: false, 1280 enumerable: true, 1281 value: constants 1282 }, 1283 INSPECT_MAX_BYTES: { 1284 configurable: true, 1285 enumerable: true, 1286 get() { return INSPECT_MAX_BYTES; }, 1287 set(val) { INSPECT_MAX_BYTES = val; } 1288 } 1289}); 1290