title: Emscripten Uncaught RangeError: Source is too large, multiple Float32Arrays
body: <p>I'm trying to run a C++ function for 4x4 matrices multiplying. After 2 days it finally works, but not as expected. </p>
  
  <p>Often parameters are being fed back to the function and then this line:</p>
  
  <pre><code>dataHeap2.set( new Uint8Array(data2.buffer) );
  </code></pre>
  
  <p>produces an error "Uncaught RangeError: Source is too large"</p>
  
  <p>At a glance it looks like it's just a normal Float32Array with 16 elements, but after looking inside it's buffer size it seems to be different</p>
  
  <pre><code>console.log(data2.buffer.bufferLength);
  </code></pre>
  
  <p>The result are not expected 64 bytes but huge numbers like 3342345. Is this the problem? I found a workaround by manually copying values(like below), returning that and then the problem disappears. Unfortunately it makes my code much slower than operating directly on buffers.</p>
  
  <pre><code>// bad solution - which works
      for(var i = 0; i &lt; 16; i++) {
          dataTarget[i] = result[i];
      }
  </code></pre>
  
  <p>Hopefully this night I'll find a better solution and I want to keep using this function as it's using a compiled C++ code using ASM.JS + SIMD for aninmating multiple characters. In pure JavaScript it's still too slow. Here's the entire function. I'm pretty sure that data2 is taking Emscripten's HEAP with it and I want to aviod it.</p>
  
  <pre><code>matrix4multiply = function(data, data2) {
      // Import function from Emscripten generated file
      var mmul_vec4 = Module.cwrap(
        'mmul_vec4', 'number', ['number', 'number', 'number']
      );
  
      var dataTarget = new Float32Array(16);
  
      // Get data byte size, allocate memory on Emscripten heap, and get pointer
      var nDataBytes = dataTarget.length * dataTarget.BYTES_PER_ELEMENT;
  
      // First matrix copy data to Emscripten heap
      var dataPtr = Module._malloc(nDataBytes);
      var dataPtr2 = Module._malloc(nDataBytes);
      var dataPtr3 = Module._malloc(nDataBytes);
  
      var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, nDataBytes);
      dataHeap.set( new Uint8Array(data.buffer) );
  
      // second matrix allocate and copy to emscripten's heap
      var dataHeap2 = new Uint8Array(Module.HEAPU8.buffer, dataPtr2, nDataBytes);
      dataHeap2.set( new Uint8Array(data2.buffer) );
  
      // target heap
      var targetHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr3, nDataBytes);
      targetHeap.set( new Uint8Array(dataTarget.buffer) );
  
      // Call the function by passing a number pointing to the byte location of 
      // the array of pointers on the Emscripten heap.  Emscripten knows what to do!
      mmul_vec4(dataHeap.byteOffset, dataHeap2.byteOffset, targetHeap.byteOffset);
  
      // get result
      var result = new Float32Array(targetHeap.buffer, targetHeap.byteOffset, 16);
  
      // bad solution - which works
      //for(var i = 0; i &lt; 16; i++) {
      //    dataTarget[i] = result[i];
      //}
  
      // Free memory
      Module._free(dataHeap.byteOffset);
      Module._free(dataHeap2.byteOffset);
      Module._free(targetHeap.byteOffset);
  
      return result;
  }
  </code></pre>
  
  <p>Edit: simplified version don't worry about malloc etc</p>
  
  <pre><code>    new Uint8Array(Module.HEAPU8.buffer, this.dataPtr, 64).set( new Uint8Array(data.buffer, data.byteOffset, 64) );
  
      // second matrix allocate and copy to emscripten's heap
      new Uint8Array(Module.HEAPU8.buffer, this.dataPtr + 72, 64).set( new Uint8Array(data2.buffer, data2.byteOffset, 64) );
  
      // multiply first two parameters and return in the last one 
      this.mmul_vec4(this.dataPtr, this.dataPtr + 72, this.dataPtr + 144);
  
      // like that it works, unfotunately copying is being made here
      return new Float32Array(Module.HEAPU8.buffer.slice(this.dataPtr + 144, this.dataPtr + 208));
      // with this version (if uncommented) there's just white screen(but it looks like the game is working.
      //return new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16);
  </code></pre>