closure-compiler: Proxy & localStorage no longer working in v20170423

last time I ran my project through Closure everything went fine (with version v20170218). But now today with version v20170423 it gets errors, with absolutely nothing changed in the file:

app.js:260: ERROR - variable current_player is undeclared
    current_player = +player;
    ^^^^^^^^^^^^^^

app.js:280: ERROR - variable localStorage is undeclared
    localStorage.setItem("savestate", JSON.stringify(savestate));
    ^^^^^^^^^^^^

app.js:312: ERROR - variable Proxy is undeclared
const undo_history = new Proxy(_move_history[0], {
                         ^^^^^

app.js:451: ERROR - variable right_click_tile is undeclared
    if (right_click_tile !== null)
        ^^^^^^^^^^^^^^^^

but in the web interface it does not get any error.

I run my file with those settings:

  • compilation_level ADVANCED_OPTIMIZATIONS
  • language_in ES7
  • language_out ES5_STRICT

Source: https://gitlab.com/gumiko/contagion/blob/master/app.js

My build script gets Closure from http://dl.google.com/closure-compiler/compiler-latest.zip

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 17 (14 by maintainers)

Most upvoted comments

@brad4d, the problem is that the compiler doesn’t know what a localStorage is. Right now you have to manually declare localStorage in an extern.js, which is weird, because Storage API have been supported by all major browsers for 10 years now, and is used often.

Here are the steps to reproduce:

Contents of app.js

localStorage.getItem("a")

Compiler arguments

java -jar closure-compiler-v20200614.jar --js ./app.js --js_output_file ./compiled.js --env BROWSER --warning_level VERBOSE

Output:

./app.js:1: ERROR - [JSC_UNDEFINED_VARIABLE] variable localStorage is undeclared
  1| localStorage.getItem("a")
     ^^^^^^^^^^^^

Does it make the issue clearer?


P.S. Example of a localStorage declaration as an extern:

/**
 * @const
 */
function localStorage() {}
/**
 * @param {string} name
 * @param {string} value
 * @return {undefined}
 */
localStorage.setItem = function(name, value) {}
/**
 * @param {string} name
 * @return {undefined}
 */
localStorage.removeItem = function(name) {}
/**
* @param {string} name
* @return {string}
*/
localStorage.getItem = function(name) {}

No it’s the other way around. All global externs are added to the window object if they don’t exist.