Arnauld
Arnauld

Reputation: 6130

Google Closure Compiler complaining about XMLHttpRequest.response type

Below is a very simplified version of some code that I'm passing to Google Closure Compiler:

"use strict";

var xhr = new XMLHttpRequest();

xhr.open("GET", "somefile", true);
xhr.responseType = "arraybuffer";

xhr.addEventListener(
  'load',
  function() {    
    var data = new Uint8Array(xhr.response);
    /* ... do something ... */
  }
);

This is basically an Ajax query to retrieve raw binary data and it is working as expected.

However, the compiler emits the following warning:

WARNING - actual parameter 1 of Uint8Array does not match formal parameter
found   : *
required: (Array<number>|ArrayBuffer|ArrayBufferView|null|number)
        var data = new Uint8Array(xhr.response);
                                  ^

I've spent some time trying to fix it with JSDoc directives, in order to explicitly define the type of 'xhr.response' as 'ArrayBuffer'.

For instance:

/** @property {ArrayBuffer} response */
var xhr = new XMLHttpRequest();

But nothing worked.

What DID finally work was to separate the variable declaration from its initialization, without adding any JSDoc directive:

var xhr;
xhr = new XMLHttpRequest();

No warning anymore.

The problem is that I don't get it. Why does it fix the problem? Was it really the right thing to do?

Upvotes: 1

Views: 356

Answers (1)

owler
owler

Reputation: 1099

Why does it fix the problem?

I think you've found a bug in the closure-compiler. You could report an issue about it.

Splitting up that line into two lines shouldn't change what the compiler is doing. For clarity, here is the line that you split.

var xhr;
xhr = new XMLHttpRequest();

I confirmed your report using online closure compiler with optimization set to Advanced.

Was it really the right thing to do?

The definition in the html5.js extern is

/**
 * @type {*}
 * @see http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-responsetype-attribute
 */
XMLHttpRequest.prototype.response;

So the error you got was reasonable. Fix it with a type-cast:

var r = /** @type {!ArrayBuffer}*/(xhr.response);
var data = new Uint8Array(r);

Try the following in the online closure compiler with optimization set to Advanced.

"use strict";

var xhr = new XMLHttpRequest();

xhr.open("GET", "somefile", true);
xhr.responseType = "arraybuffer";

xhr.addEventListener(
  'load',
  function() {
    var r = /** @type {!ArrayBuffer}*/(xhr.response);
    var data = new Uint8Array(r);
    /* ... do something ... */
  }
);

It works for me there. I also get the error you reported with your original version. Note however that with optimization set to "Simple" we don't get the error.

Upvotes: 1

Related Questions