When packing byte data into a wider integer, all bytes must be treated as unsigned and all operations must be performed unsigned.
This requires using bitwise operations:
for (var i = 0; i < array.length; i++) {
value = (value << 8) | array[i];
}
But this is limited to 32-bit values because JavaScript ignores higher bits with bitwise operations.
A possible solution (I have not tested it) would be making the values unsigned:
for (var i = 0; i < array.length; i++) {
value *= 256;
if (array[i] < 0) {
value += 256 + array[i];
} else {
value += array[i];
}
}
The trick here is that the array values are bytes in the range -128 to +127. If a byte value is negative, 256 is added to make it the corresponding unsigned value.
It should work for up to 63 bits when the operations are performed using integers. If the JavaScript interpreter decides to perform floating point operations internally, the result will become inexact with more than 53 bits.
So there is no solution (as far as I know) for 128 bits (16 bytes).
[EDIT]
Because you need integer operations without rounding errors here, you can not expect proper results for final values greater than
Number.MAX_SAFE_INTEGER - JavaScript | MDN[
^] which is limited to 53 bits (the number of mantissa bits for double precision floating point values).
[/EDIT]