I think what's going on here is that subarray() is another view on the same backing buffer. While slice() creates a new buffer for you.
For example:
> x = new Int8Array(10)
Int8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
> x.buffer.byteLength
10
> x.subarray(1, 3).length
2
> x.subarray(1, 3).buffer.byteLength
10
So the length is small, but the buffer behind it is still the full original size.
> x.slice(1, 3).length
2
> x.slice(1, 3).buffer.byteLength
2
But a slice() has the right buffer size.
In other words, when you pass views on HEAP8, the browser is copying the entire buffer behind that, which is big - all of memory. You need to make a new buffer of the right size.
Note that you may be able to make this even more efficient using transfer,