Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError in decode.min.js #881

Closed
stefanloerwald opened this issue Feb 7, 2021 · 5 comments
Closed

TypeError in decode.min.js #881

stefanloerwald opened this issue Feb 7, 2021 · 5 comments

Comments

@stefanloerwald
Copy link

stefanloerwald commented Feb 7, 2021

Hi, I've just downloaded decode.min.js and integrated it into my app according to the these Microsoft docs.

I get a TypeError: e.Q is not a function.
When pretty-printing the file in dev-tools, the error is in this section of the file:

   // this starts in line 1195 of the prettified code
    function le(e, t, i, n, a, o) {
        var r = Pe(t + i);
        if (r.length != e.length)
            throw "Corrupted brotli dictionary";
        for (var s = 0, l = n.length, c = 0; c < l; c += 2) {
            var d = n.charCodeAt(c) - 36
              , h = n.charCodeAt(c + 1) - 36;
            s += d;
            for (var f = 0; f < h; ++f)
                r[s] |= 128,
                s++
        }
        for (var c = 0; c < o.length; ++c)
            a[c] = o.charCodeAt(c) - 65;
        e.Q(r)
    }

Is this a problem with the minified JS file or with the code calling it?

The code that interacts with brotli is this:

<script src="decode.min.js"></script>
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type !== 'dotnetjs' && location.hostname !== 'localhost') {
        return (async function () {
          const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
          if (!response.ok) {
            throw new Error(response.statusText);
          }
          const originalResponseBuffer = await response.arrayBuffer();
          const originalResponseArray = new Int8Array(originalResponseBuffer);
          const decompressedResponseArray = BrotliDecode(originalResponseArray);
          const contentType = type === 
            'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
          return new Response(decompressedResponseArray, 
            { headers: { 'content-type': contentType } });
        })();
      }
    }
  });
</script>
@stefanloerwald
Copy link
Author

stefanloerwald commented Feb 10, 2021

I had a deeper look into the javascript and the minified version is obviously invalid: The corresponding code unminified is:

  function unpackDictionaryData(dictionary, data0, data1, skipFlip, sizeBits, sizeBitsData) {
    var /** @type{!Int8Array} */ dict = toUsAsciiBytes(data0 + data1);
    if (dict.length != dictionary.length) {
      throw "Corrupted brotli dictionary";
    }
    var /** @type{number} */ offset = 0;
    var /** @type{number} */ n = skipFlip.length;
    for (var /** @type{number} */ i = 0; i < n; i += 2) {
      var /** @type{number} */ skip = skipFlip.charCodeAt(i) - 36;
      var /** @type{number} */ flip = skipFlip.charCodeAt(i + 1) - 36;
      offset += skip;
      for (var /** @type{number} */ j = 0; j < flip; ++j) {
        dict[offset] |= 0x80;
        offset++;
      }
    }
    for (var /** @type{number} */ i = 0; i < sizeBitsData.length; ++i) {
      sizeBits[i] = sizeBitsData.charCodeAt(i) - 65;
    }
    dictionary.set(dict);
  }

There is exactly one call to this method, and it's four lines further down:

    var /** @type{!Int8Array} */ dictionaryData = new Int8Array(122784);
    var /** @type{!Int32Array} */ dictionarySizeBits = new Int32Array(25);
    unpackDictionaryData(dictionaryData, "...

So it's obvious, that the first arg to the method is of type Int8Array. The minifier replaced set by Q, which is nonsense. So this was created by an overly aggressive minifier.

The attached minified version was generated using the following Dockerfile:

FROM node
WORKDIR /src
RUN npm i minify -g
RUN wget https://github.com/google/brotli/raw/master/js/decode.js
RUN minify decode.js > decode.min.js

Until the actual build pipeline for these files is fixed, I'd suggest to simply replace the files with the ones attached.

BR
Stefan

(Note: a previous version of this comment incorrectly stated that there was unused code in the JS file. I apologise for this mistake. However, the analysis that the minified file is not working still stands)

@stefanloerwald
Copy link
Author

It's been months on this topic without any response. I must say I find it bizarre that such a trivially fixable issue isn't even responded to. Clearly other people are affected too. Please just use a non-broken minifier to produce a correct version of your code.

Thanks
Stefan

@eustas
Copy link
Collaborator

eustas commented Jun 24, 2021

Hello. Sorry for the super-long delay. Could you, please, check that decode.min.js works for you now?

@eustas
Copy link
Collaborator

eustas commented Jun 24, 2021

Important: now decode.js / decode.min.js is a module; so the updated usage example looks like this:

<html>
<body>
  <script type="module">
    import {BrotliDecode} from './decode.min.js';
    let ukkonooa = [
      0x1b, 0x76, 0x00, 0x00, 0x14, 0x4a, 0xac, 0x9b, 0x7a, 0xbd, 0xe1, 0x97,
      0x9d, 0x7f, 0x8e, 0xc2, 0x82, 0x36, 0x0e, 0x9c, 0xe0, 0x90, 0x03, 0xf7,
      0x8b, 0x9e, 0x38, 0xe6, 0xb6, 0x00, 0xab, 0xc3, 0xca, 0xa0, 0xc2, 0xda,
      0x66, 0x36, 0xdc, 0xcd, 0x80, 0x8d, 0x2e, 0x21, 0xd7, 0x6e, 0xe3, 0xea,
      0x4c, 0xb8, 0xf0, 0xd2, 0xb8, 0xc7, 0xc2, 0x70, 0x4d, 0x3a, 0xf0, 0x69,
      0x7e, 0xa1, 0xb8, 0x45, 0x73, 0xab, 0xc4, 0x57, 0x1e
    ];
    let lyrics = BrotliDecode(new Uint8Array(ukkonooa));
    console.log(String.fromCharCode.apply(null, new Uint16Array(lyrics)));
  </script>
</body>
</html>

@eustas eustas closed this as completed Jun 24, 2021
@stefanloerwald
Copy link
Author

Hi @eustas,

I can confirm that the new version works. Thank you.

Best regards
Stefan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants