Created
May 28, 2016 07:39
-
-
Save yyang/f88c4cfa49daa6db2f4855d018aadbdc to your computer and use it in GitHub Desktop.
Buffer polyfill.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import semver from 'semver'; | |
let supportedEncoding = ['ascii', 'utf8', 'utf16le', 'ucs2', 'base64', | |
'binary', 'hex']; | |
let currentVersion = semver.clean(process.version); | |
/** | |
* Polifills Object to obtain modern APIs. | |
* @param {String} targetVersion Target version to be polyfilled. | |
* @param {Object} object Object to polyfill. | |
* @param {Object} methods An object of all the methods to polyfill. | |
* @return {Object} Polyfilled Object (not necessary to be used). | |
*/ | |
function polyfill(targetVersion, object, methods) { | |
if (!semver.satisfies(currentVersion, targetVersion)) { | |
return; | |
} | |
Object.getOwnPropertyNames(methods).forEach(function(name) { | |
Object.defineProperty(object, name, { | |
configurable: false, | |
enumerable: false, | |
value: methods[name], | |
writable: false | |
}); | |
}); | |
return object; | |
} | |
polyfill('<5.10.0', Buffer, { | |
from: function() { | |
// Class Method: Buffer.from(array) | |
// Original Method: new Buffer(array) | |
// Allocates a new Buffer using an array of octets. | |
if (Array.isArray(arguments[0])) { | |
return new Buffer(arguments[0]); | |
} | |
// Class Method: Buffer.from(str[, encoding]) | |
// Original Method: new Buffer(str, [encoding]) | |
// Allocates a new buffer containing the given str. | |
// Encoding defaults to 'utf8'. | |
if (typeof arguments[0] === 'string') { | |
if (arguments[1] && supportedEncoding.indexOf(arguments[1]) !== -1) { | |
return new Buffer(arguments[0], arguments[1]); | |
} | |
return new Buffer(arguments[0]); | |
} | |
// Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) | |
// Original Method: new Buffer(arrayBuffer) | |
// When passed a reference to the .buffer property of a TypedArray instance, | |
// the newly created Buffer will share the same allocated memory as the | |
// TypedArray. | |
// Note: Requires nodejs version 5.4.0 or greater. Otherwise there won't be | |
// a equivilant behaviour. | |
if (arguments[0] instanceof ArrayBuffer) { | |
if (semver.lt(currentVersion, '5.4.0')) { | |
throw new TypeError('new Buffer from ArrayBuffer is only supported' + | |
'by nodejs version v5.4.0 and greater'); | |
} | |
// Creates new buffer; | |
let buffer = new Buffer(arguments[0]); | |
// Checks the first argument to determine to slice or not | |
let byteOffset; | |
let length; | |
if (typeof arguments[1] === 'number' && arguments[1] < buffer.length) { | |
byteOffset = arguments[1]; | |
} else { | |
byteOffset = 0; | |
} | |
if (typeof arguments[2] === 'number') { | |
if (arguments[2] < buffer.length - byteOffset) { | |
length = arguments[2]; | |
} | |
} else { | |
length = buffer.length - byteOffset; | |
} | |
return buffer.slice(byteOffset, length); | |
} | |
// Class Method: Buffer.from(buffer) | |
// Original Method: new Buffer(buffer) | |
// Copies the passed buffer data onto a new Buffer instance. | |
if (arguments[0] instanceof Buffer) { | |
if (semver.gte(currentVersion, '0.11.15')) { | |
return new Buffer(arguments[0]); | |
} | |
// Polyfill for lower versions. | |
let buffer = new Buffer(arguments[0].length); | |
arguments[0].copy(buffer); | |
return buffer; | |
} | |
throw new TypeError('must start with buffer, array or string'); | |
}, | |
alloc: function() { | |
// Detects if exception should be thrown. | |
if (typeof arguments[0] !== 'number') { | |
throw new TypeError('must start with number'); | |
} | |
// Values. | |
let buffer = new Buffer(arguments[0]); | |
let fill = arguments[1]; | |
let encoding = arguments[2]; | |
// Fills buffer | |
if (encoding && supportedEncoding.indexOf(encoding)) { | |
// Suppots encoded fill | |
if (semver.gte(currentVersion, '5.7.0')) { | |
buffer.fill(fill, encoding); | |
// Otherwise write to "fill" | |
} else { | |
let fillLength = (new Buffer(fill, encoding)).length; | |
let repeat = ~~(buffer.length / fillLength) + 1; | |
for (let i = 0; i < repeat; i++) { | |
buffer.write(fill, i * fillLength, encoding); | |
} | |
} | |
// Encoding not specified, otherwise fill safe value. | |
} else { | |
buffer.fill(fill ? fill : undefined); | |
} | |
return buffer; | |
}, | |
allocUnsafe: function() { | |
// Detects if exception should be thrown. | |
if (typeof arguments[0] !== 'number') { | |
throw new TypeError('must start with number'); | |
} | |
return new Buffer(arguments[0]); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment