blickly / closure-compiler-issues

0 stars 0 forks source link

Advanced Optimizations not removing multiple functions off an object #117

Closed blickly closed 9 years ago

blickly commented 9 years ago
What steps will reproduce the problem?

Compile the following code:

// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level ADVANCED_OPTIMIZATIONS
// @formatting pretty_print
// ==/ClosureCompiler==

function init() {
  var o = function () {};
  o.foo = function () { return 1; };
  o.bar = function () { return 2; };
}

init();

What is the expected output? What do you see instead?

Expected:
Code is compiled down to 0 bytes

Actual:

function b() {
  function a() {
  }
  a.b = function() {
    return 1
  };
  a.a = function() {
    return 2
  }
}
b();

What version of the product are you using? On what operating system?
Compiler on http://closure-compiler.appspot.com/home

Please provide any additional information below.

The code WILL compile down to nothing if you:

1. Define foo and bar on o.prototype:

function init() {
  var o = function () {};
  o.prototype.foo = function () { return 1; };
  o.prototype.bar = function () { return 2; };
}
init();

2. Have only one function declared on `o`:

function init() {
  var o = function () {};
  o.foo = function () { return 1; };
}
init();

Original issue reported on code.google.com by frawl021 on 2010-02-23 18:52:39

blickly commented 9 years ago
a large part of this is due to the function inlining rules. There's a very specific

reason why init() isn't getting inlined in that case. I have to go thru my email to

figure out why that is and what is ok to tweak to make this happen. (John wrote the

rules, and he's currently on a multi-week vacation).

Another way to fix this would make the unused-variable remover better.

Original issue reported on code.google.com by Nicholas.J.Santos on 2010-02-26 02:43:19

blickly commented 9 years ago
It might because inlining to global scope would introduce the locals as global 
variables and would hurt renaming in the already populated global scope.

Or we should collapse properties within function scope and let local function inlining

do its thing.

Original issue reported on code.google.com by acleung on 2010-02-26 19:52:49

blickly commented 9 years ago
In working case 1, "remove unused prototype properties pass" is reducing the function
to, which "remove unused variables" can reduce to a empty function:
  function init() {
    var o = function () {};
  }
In working case 2, "inline variables" is creating a single removal statement:
  function init() {
    (function(){}).foo = function () { return 1; }
  }

For the root case of this issue, the function is not being inlined because the
function inliner has a basic rule "don't inline any function with inner function".

There are couple choices here:
1) Create a "remove unused property" pass.  The question being why doesn't this
currently exist?  Was it not done for a reason?
2) Create a new set of rules about when a function with inner functions can be inlined.
3) Create a pass to extract function out of function scope when possible.

#1 seems like it would be most generally useful.
I'm also curious why namespace collapsing doesn't work here.

Original issue reported on code.google.com by concavelenz on 2010-03-18 01:12:40

blickly commented 9 years ago
(No text was entered with this change)

Original issue reported on code.google.com by concavelenz on 2010-03-23 00:37:59

blickly commented 9 years ago
Remove unused variable can now remove "o" in this example.

Original issue reported on code.google.com by concavelenz on 2010-10-01 17:06:35