Resize ArrayBuffer
The way to do that would be ArrayBuffer.transfer(oldBuffer, newByteLength)
, like so:
var buffA = new ArrayBuffer(30);
var buffB = ArrayBuffer.transfer(buffA, 40);
// buffA is now an empty array buffer (`buffA.byteLength === 0`)
// whereas buffB is a new buffer that starts with a's contents
// and ends with 10 bytes that are 0s.
// Much faster than manually copying. You could even just do:
var buffA = new ArrayBuffer(30);
buffA = ArrayBuffer.transfer(buffA, 40);
// Or as a prototype method
ArrayBuffer.prototype.resize = function(newByteLength) {
return ArrayBuffer.transfer(this, newByteLength);
}
var buffA = new ArrayBuffer(30);
buffA = buffA.resize(40);
However (as of October 2017) there is 0% browser support (not even Node.js support) and is not even drafted yet.
Until this is available, you can use the polyfill given on the page, which copies 8 bytes at a time, so is relatively quick for large arrays (Though it does not empty the given array, which is impossible to do).
Here is a modified version using TypeArray.prototype.set
instead of for loops:
if (!ArrayBuffer.transfer) {
ArrayBuffer.transfer = function(oldBuffer, newByteLength) {
var srcBuffer = Object(oldBuffer);
var destBuffer = new ArrayBuffer(newByteLength);
if (!(srcBuffer instanceof ArrayBuffer) || !(destBuffer instanceof ArrayBuffer)) {
throw new TypeError('Source and destination must be ArrayBuffer instances');
}
var copylen = Math.min(srcBuffer.byteLength, destBuffer.byteLength);
/* Copy 8 bytes at a time */
var length = Math.trunc(copylen / 64);
(new Float64Array(destBuffer, 0, length))
.set(new Float64Array(srcBuffer, 0, length));
/* Copy the remaining 0 to 7 bytes, 1 byte at a time */
var offset = length * 64;
length = copylen - offset;
(new Uint8Array(srcBuffer, offset, length))
.set(new Uint8Array(destBuffer, offset, length));
return destBuffer;
};
}
[EDIT]
alternate version of the above that doesn't use ArrayBuffer namespace, and takes a slightly different approach
function arrayBufferTransfer(oldBuffer, newByteLength) {
const
srcArray = new Uint8Array(oldBuffer),
destArray = new Uint8Array(newByteLength),
copylen = Math.min(srcArray.buffer.byteLength, destArray.buffer.byteLength),
floatArrayLength = Math.trunc(copylen / 8),
floatArraySource = new Float64Array(srcArray.buffer,0,floatArrayLength),
floarArrayDest = new Float64Array(destArray.buffer,0,floatArrayLength);
floarArrayDest.set(floatArraySource);
let bytesCopied = floatArrayLength * 8;
// slowpoke copy up to 7 bytes.
while (bytesCopied < copylen ) {
destArray[bytesCopied]=srcArray[bytesCopied];
bytesCopied++;
}
return destArray.buffer;
}
No set on the ArrayBuffer itself. There is set
on the TypedArray though. Use like this:
var oldBuffer = new ArrayBuffer(20);
var newBuffer = new ArrayBuffer(40);
new Uint8Array(newBuffer).set(oldBuffer);