0

I have a problem where the Closure Compiler renames a global variable something like x.sa.xa but in all function where that global variable is referenced the compiler renames it something else like H.sa.xa

When I view the HTML page I get a JavaScript TypeError: H.sa.xa is undefined.

// Top-level namespace for all the code
var nam = nam || {};

(function($, nam) {

 goog.provide('nam.jsConfig');

 nam.jsConfig.cookies = {"RECENT_ITEMS": "recentitems"};

})($, nam);

(function($, nam) {
 goog.provide('nam.util.cookie');
 nam.util.cookie.readMyCookie = function () {
  var ritems_cookie = nam.util.cookie.JSONCookie.get(nam.jsConfig.cookies['RECENT_ITEMS']);
 };
})($, nam);


Closure Compiled Code:
x.sa = {};
x.sa.xa = {RECENT_ITEMS:"recentitems"};

H.a = {};
H.a.cookie = {};
H.a.Tm = function() {
  var a = H.a.cookie.ja.get(H.sa.xa.RECENT_ITEMS);
};

For some reason the Closure Compiler is referencing H.sa.xa.RECENT_ITEMS instead of x.sa.xa.RECENT_ITEMS

Any reason why the compiler is doing this this?

Chris
  • 816
  • 4
  • 11
  • 23
  • 4
    You would likely get a better response if you showed the offending code and its context. Closure has ways to specify that certain variables should not be renamed because they are referenced externally. – jfriend00 Mar 24 '13 at 15:44
  • I'm not able to reproduce the issue with that code snippet. However I would try NOT passing your namespace `nam` as an argument to your anonymous function wrappers and seeing if the issue still occurs. – Chad Killingsworth Mar 25 '13 at 11:45
  • Looks fine to me as well. Maybe Plovr's old compiler version is biting you or one of its customizations. But generally, the anonymous closures around the goog.provides are unusual for Closure code. – John Mar 26 '13 at 15:05

3 Answers3

0

The only way I can interpret your question is that one of two things is happening:

  1. There is an issue with the Closure Compiler's obfuscating and minimizing code, or
  2. The error you are seeing is from JavaScript running outside of the code compiled by the Closure Compiler that is referencing a compiled variable directly.

If it is the former, you should isolate the case that is causing variable misalignment and submit it as a bug to Google. All of us using the Closure Compiler would greatly appreciate it.

If instead, as I suspect, it is the latter, you are most likely not exporting the global variable you wish to use outside of the compiled code. The easiest way to do this is to call goog.exportSymbol() function to make the global variable available outside of your code assembled by the Closure Compiler. For example, if you wished to access the property sandwich.meat.Ham in compiled mode from non-compiled code, you could do the following:

goog.exportSymbol('sandwich.meat.Ham', sandwich.meat.Ham);

Then you could have some code that exists outside of your compiled code that references the exported variable:

function() {
    var meat = new sandwich.meat.Ham();
}
Technetium
  • 5,902
  • 2
  • 43
  • 54
  • Thank you for your help. It looks like it's an obfuscating and minimizing code issue. I have updated my post to show the offending code. – Chris Mar 25 '13 at 10:17
0

Let me guess what you are doing: compiling each file independently in ADVANCED mode. If so, this isn't how ADVANCED mode works. In advanced mode if you want to share variable and properties between compilations jobs you need to export them.

John
  • 5,443
  • 15
  • 21
0

There are much more significant issues in the code example you provided. For one

goog.provide('nam.util.cookie');

was turned into

H.a = {};
H.a.cookie = {};

Yet later this code:

nam.util.cookie.readMyCookie = function () {...

was turned into

H.a.Tm = function() {...

Where one would expect it should be

H.a.cookie.Tm = function() {...

Additionally, the fact that you use nam as the base namespace for both halves of the uncompiled code and that it gets turned into separate x and H namespaces, respectively, also suggests more is at play. Some suggestions:

  • If you wish to use the module pattern, put the provide/require statements outside of the module
  • Don't manually create namespaces with stuff like var nam = nam || {} because provide does this for you already
  • As others have mentioned, both files containing nam.jsConfig and nam.util.cookie should be included in a single compilation
  • Make sure you goog.require('nam.jsConfig') in the file with nam.util.cookie.readMyCookie, to ensure the dependency requirements are met

FWIW, we use closure in an extensive application with hundreds of files, containing interdependencies like this. I would be highly suspect that the issue lies not with the tools, but instead with how they are being used.

jordancpaul
  • 2,954
  • 1
  • 18
  • 27