DEV Community

Marko V
Marko V

Posted on • Updated on

"Uint8Array, we need to have a talk." -- IE11

Yesterday's post, where a pre-commit was enforced/distributed among the team, linting errors were found a-plenty. This was to be expected of course, since there were 132000 linting errors in the javascript code that has been growing over the past 5 years. However, 110000 of those are just within the last year.

Hence me trying now to enforce this to get that in control.

So I was approached today by a fellow dev in my team to help him with a linting error that he couldn't understand at first.

It all started with let.

The first error he encountered was a parsing error for eslint. ESlint couldn't get past the "let variableName = {}" so converting all let and const definitions to var. I know what you're thinking.... but this is fine, it's not typescript, it's not es6 enabled either in .eslintrc, so it's by design because let and const, are not fully supported in IE11 and we still have IE11 customers in the application. 30% in fact.

So once all of the "let"s were converted. More issues surfaced of course. Most of which were possible to be resolved with --fix with eslint. So what we were left with were just semantics/styling for the exception of one. Uint8Array.

Now Uint8Array is a ES6 feature partially supported by IE11. Uint8Array however, was used with an iterator constructor, which ISN'T supported by IE11. So the code had to be refactored.

The original block of code.

// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
if ($window.navigator.msSaveBlob) {
  let byteCharacters = atob(response.data);
  let byteNumbers = new Array(byteCharacters.length);
  for (var i = 0; i < byteCharacters.length; i++)
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  let byteArray = new Uint8Array(byteNumbers);
  var blob = new Blob([byteArray], { type: 'application/octet-stream' });
  $window.navigator.msSaveOrOpenBlob(blob, filename);
}
Enter fullscreen mode Exit fullscreen mode

After the style-related issues + let/const were fixed. We had this.

// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
if ($window.navigator.msSaveBlob) {
  var byteCharacters = atob(response.data);
  var byteNumbers = new Array(byteCharacters.length);
  for (var i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  var byteArray = new Uint8Array(byteNumbers);
  var blob = new Blob([byteArray], { type: 'application/octet-stream' });
  $window.navigator.msSaveOrOpenBlob(blob, filename);
}
Enter fullscreen mode Exit fullscreen mode

Not only was the developer that did this inconsistent, because they had a "var blob" in there. Meaning they likely just cut-n-pasted code from elsewhere and joined with whatever was there before.

Also, I think it was entirely untested. When I ran the steps to reproduce this in the IE11 console, instantiating a Uint8Array from another array with data (i.e. iterator) the Uint8Array only took the length of the other array to instantiate itself to the appropriate size, but it didnt take the data. Meaning this code that we had, would not work. It would be an array of bytes where all the bytes were set to 0 and the user, if they clicked on the button tied to this function, would get a very useless file.

To fix this, it was quite simple. The Uint8Array, could simply take the same charCodeAt conversion happening in the for-loop above, directly. So instantiating it to the length of the byteCharacters variable, we just had to fill it with data using simple byteArray[i] = byteCharacters.charCodeAt(i); So we reduced memory usage and fixed a previously untested bug.

Just by linting!

// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
if ($window.navigator.msSaveBlob) {
  var byteCharacters = atob(response.data);
  var byteArray = new Uint8Array(byteCharacters.length);
  for (var i = 0; i < byteCharacters.length; i++) {
    byteArray[i] = byteCharacters.charCodeAt(i);
  }
  var blob = new Blob([byteArray], { type: 'application/octet-stream' });
  $window.navigator.msSaveOrOpenBlob(blob, filename);
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)