Google Closure Compiler and Javascript Objects in Advanced option

108 views
Skip to first unread message

Wayne Fulton

unread,
Oct 16, 2024, 7:45:55 PM10/16/24
to Closure Compiler Discuss

I love what Google Closure does, and after discovering what Javascript Objects can do (Speed! as fast or faster than local vars), I love them too. But when Google Closure (Advanced option) renames the variables, objects change from the normal expected Object syntax into simple global var syntax:

Example: var Obj = {a: 0, b: 0, c: 0) format that instead instead comes out like this real case:

var u = 0, v = 0, w = 0, x = 4769.83, y = 0, p = document.getElementById("new"), q = document.getElementById("old"), z = document.getElementById("res"), m = document.getElementById("res2"), A = document.getElementById("tb0"), n = document.getElementById("yrs"), B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 1, I = 0, J = 0, K = 0, L = /^20\d\d/, M = 0, N = 0, O = document.getElementById("tab").rows, r = "object" !== typeof f || -1 == P(f[0], 18) && -1 == P(f[1], 0) ? 0 : 1;

This changed syntax is no different than it were just ordinary global varibles (no semicolon object key definition references, and no periods of u.b key object access syntax). How can this be? What do I not understand? It is still Javascrip code, but nothing suggests Objects. I don't understand how they can still be Objects (without the semicolons and periods of keys). It seems the opposite of the Closure goals.

But when the Google Closure Simple option choice (no renaming) runs, it leaves the object syntax in place, exactly recognizable.  So why discard that in Advanced?

Is there any explanation, or better, any work around, about this issue?


Wayne Fulton

unread,
Oct 17, 2024, 10:29:36 AM10/17/24
to Closure Compiler Discuss
I have now tried timing the difference in the original code (where the object was clearly present) and the Google Closure Compiler (Advanced mode) where the code showed no sign of an object.  And the timing (1e10 loops) was the SAME, 8 or 10 or 50 seconds.    I have no idea how or why that it could be true, but I am pleased.   Also extremely curious about how or why it can possibly be the same time.
In the test either way,  the Local var time was about 80% of the Object, and the the global var time was 5x the Object, even though the Object was global too. I understand the why of that last part, because it is an object with embedded memory address.
I sure would like to hear a few details about this situation, of Closure totally hiding or likely removing the object.

I found this link  
that says AVOID OBJECTS and use better types.   It is dated 2021 which I think is after the speedup.
I disagree with that part of it.   I need global objects to retain permanance between app calls, and also to group parms like a C structure, and now they are fast.

Also the object situation (of containing the memory address) causing
 Obj.a  = Obj.b   to both contain the same address, i.e. one variable at that address now.
That seems to have been fixed recently (last year or so), at least I cannot duplicate the previous problem any more.

Where is this kind of stuff written up, so we can learn it?   It affects how we have to code.

Laura Harker

unread,
Oct 17, 2024, 10:52:54 AM10/17/24
to closure-comp...@googlegroups.com
Hi,

Closure Compiler ADVANCED mode is focused primarily on decreasing compressed code size, with runtime performance being secondary, but it does try to avoid regressing performance. You can see some more information here: https://developers.google.com/closure/compiler/docs/api-tutorial3.

When it comes to having objects in the global scope, we recommend considerring --isolation_mode=IIFE (https://github.com/google/closure-compiler/wiki/Flags-and-Options#output), to wrap your code in an IIFE & avoid polluting the global scope unnecessarily. This is useful if your JS runs on the same page as other JS, to avoid problems where multiple scripts define the same global symbol. If you need global state, you can still explicitly write `window.Foo = Foo`, but `var Foo = 0` would be scoped inside the IIFE.

https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System specifically calls out the use of the Object type - /** @type {!Object} */. Apologies for the confusion. It's not suggesting to avoid using JavaScript objects generally.

> I sure would like to hear a few details about this situation, of Closure totally hiding or likely removing the object.

I'm afraid I don't completely follow, do you have a specific before/after example you could share?

Best,
Laura


--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/closure-compiler-discuss/cf83ab3d-3b16-4696-967a-76d7575d5b36n%40googlegroups.com.

Wayne Fulton

unread,
Oct 17, 2024, 7:47:46 PM10/17/24
to Closure Compiler Discuss
Thank you Laura for responding.  I'm really confused today. I can still today repeat the var string shown in the original post where the online Closure Advamced option replaces the object with just global vars, so that is still true, at least in that app.  So my overall concern is how can I (still use on-line Advanced Closure) and retain my object?  Again, the Simple option did retain the Object.

Yet in the significantly larger different app where I did the speed tests that says original Javascript is the same speed as the Closure Advanced version, now today when I inspect it closer, I see and realize that Closure did NOT replace the object with simple global vars.   Object is still an object, in form and speed.  In that app.

There is a large file size difference, but I cannot see nor imagine any difference in the apps that could cause that difference, but I sure would like to know how  to retain my objects.  Both are (large, ~60 keys) simple objects declared in form of  var Obj = [a.0, b:0, c.0};

Using the online Closure compiler,  I would also like to know how I can set the --isolation_mode=IIFE  flag? In what form and where do I type it?   No options in online Closure, so on-line is likely my problem.    In the JS file, that text is not accepted  as valid Javascript.  I tried putting it in a /**  */ comment as shown on another closure page about using extern which did not work (nor did it work for the extern).  So I am missing some overall concept.

Wayne Fulton

unread,
Oct 18, 2024, 11:47:46 AM10/18/24
to Closure Compiler Discuss
Laura,  please consider this to be a new bug report.  I'd  say a very serious one.   The difference in my Google Closure compliled apps (with objects that either worked before or now don't work)  is the DATE COMPILED with Google Closure Compiler.   

I request that you please ask the Closure Compiler crew to take a few minutes to quickly check the Closure result (of on-line version at https://closure-compiler.appspot.com/home  , Advanced option. Simple option is still OK).  Run it against a Javascript file that contans a simple object (form of global var Obj = {a:0, b:0, c:0}  ), and then simply search the Closure result for the expected and necessary remaining text string ={  that any object declaration should still have but doesn't have today (and does not have the key colons nor dot separators either). Objects become simple global vars, which are slow instead of still fast.   

Checking my files, I don't know the exact date, but the current version will fail, and I suspect any this month.  This is a bug that occurred sometime after 8/9/24, which was still OK then.  Date doesn't matter,  today it is a bug.     It was OK before, and objects remained objects. and now they don't.   Since becoming simple global variables now, they run several times slower, which cannot be an intended goal.    Coding with all global vars cannot be good plan.  Being an object with embedded memory addresses as intended is greatly faster than a simple global var.  Seems quite serious to me and I imagine all would agree.

A humorous point to me is that I discovered in this time frame that  Obj.a = Obj.b  no longer became the same embedded address location, which I thought it was great that was fixed (I cannot imagine any advantage of that, and you'd think it could be programmed out, to NOT rewrite the address).  But that notion was too hasty,  now, it seems clear the most obvious cause was only because they were no longer objects.  :)


lha...@google.com

unread,
Oct 18, 2024, 12:11:09 PM10/18/24
to Closure Compiler Discuss
> Using the online Closure compiler,  I would also like to know how I can set the --isolation_mode=IIFE  flag? In what form and where do I type it?   No options in online Closure, so on-line is likely my problem

I don't believe the online compiler service supports this option, no. The Closure Compiler team treats the compiler service as mainly for debugging & showing small reproductions of problems. You can set flags with https://www.npmjs.com/package/google-closure-compiler.

my overall concern is how can I (still use on-line Advanced Closure) and retain my object?

Flattening object property keys is an intended behavior of advanced mode: https://developers.google.com/closure/compiler/docs/limitations#implications-of-object-property-flattening. As I said above, we don't consider this a bug, because developers generally do want to load their code in an IIFE create local instead of global variables. If you do need a global variable, see also https://developers.google.com/closure/compiler/docs/externs-and-exports for how to correctly work with ADVANCED mode.

Best,
Laura

Johannes Nel

unread,
Oct 18, 2024, 7:43:57 PM10/18/24
to closure-comp...@googlegroups.com
>>. If you do need a global variable, see also https://developers.google.com/closure/compiler/docs/externs-and-exports for how to correctly work with ADVANCED mode.

^ this is what you need and how you cross the global bridge with closure.

Wayne Fulton

unread,
Oct 21, 2024, 12:11:12 PM10/21/24
to Closure Compiler Discuss
I am disallusioned to learn that objects in Google Closure Compiler now longer work anything like Javascript Objects work.  They used to until recently. Now the performance difference of each converted individual global var becomes seriously worse than what global objects can do.  Putting the object in a function would not still be an object in Closure, and it would lose permanance between calls, and it would have to be passed to each other function using it, but at least performance should be acceptable.   

I fail to see any point of using objects as now in Google Closure, and I hope someone will rethink that very soon.  

 I can see how an external object  that was not itself compliled by Google Closure could restore all features of objects, except I think externs do not work in the online Closure version I want to use.

lha...@google.com

unread,
Oct 21, 2024, 3:33:17 PM10/21/24
to Closure Compiler Discuss
> Putting the object in a function would not still be an object in Closure, and it would lose permanance between calls, and it would have to be passed to each other function using it

I do strongly suggest reading through https://developers.google.com/closure/compiler/docs/externs-and-exports. I'll also  note that Closure ADVANCED mode is very opinionated, intentionally, and does not work well with code that (often completely reasonably) does not conform to its assumptions.

As a more concrete example, Closure will leave

   window.obj = {foo: 0, bar: 1}

as an object because it's an "export". Closure just renames its properties, as it does more generally in the ADVANCED mode.

So in the online compiler the result is this:

  window.i={h:0,g:1};

Wayne Fulton

unread,
Oct 26, 2024, 7:56:10 PM10/26/24
to Closure Compiler Discuss
Thanks. I see now that Closure Advanced does create the object, and renames the vars, so that part does work afterall.
and very much would like to use it, but copying that help (with my code  names in it), of:
/** * @fileoverview Public API of my_math.js.
 * @externs */ 
const myMath = {};

does not work for me. I need better example of complete syntax instructions.  Is that to be found anywhere?
The primary .js file can only see the compiled external. So how does it's closure know how to match those renamed object variables?

I have learned that building the object into the  function (instead of turning into simple global vars) does work in Closure Advanced.
However it  initalizes at every call (speed), and does not retain data permanance between calls,   and must be passed to the other functions.  But overall, it still seems much better than making them be simple global vars.
Reply all
Reply to author
Forward
0 new messages