Closure compiler behaviour with wrapped objects

37 views
Skip to first unread message

Manas Jayanth

unread,
Jul 18, 2018, 12:45:14 PM7/18/18
to Closure Compiler Discuss

I'm trying to get the closure compiler to inline some of my code wrapped in configuration objects in SIMPLE mode without any type annotations. React does this and managed to bring down bundle sizes


I observed the following:


a.js


(function main() {

  const config = {
    log(m) {
      console.log(m);
    }
  }

  function reconciler(c) {
    const log = c.log;
    log('jere');
  }

  reconciler(config);

}())


when compiled returns


a.min.js


(function() {
  (function(a) {
    a = a.log;
    a("jere");
  })({
    log: function(a) {
      console.log(a);
    }
  });
})();


And,


b.js


(function main() {

  const config = {
    log(m) {
      console.log(m);
    }
  }

  function reconciler(c) {
    const log = c.log;
    c.log('here');
    // log('jere');
  }

  reconciler(config);

}())


when compiled gives,


b.min.js


(function() {
  console.log("here");
})();


On the other hand,


function main(){
  const config = {
    log: function log(m) {
      console.log(m);
    }
  };

  const log = config.log;

  log('m');
  log('m');
  log('m');
  log('m');
}

main()


gives


function main() {
  console.log("m");
  console.log("m");
  console.log("m");
  console.log("m");
}
main();


How does Closure Compiler inline? Is there is definite way to get it to inline wrapped functions?

John Lenz

unread,
Jul 18, 2018, 1:32:58 PM7/18/18
to closure-compiler
The compiler's inliner is a heuristic that tries to minimize the final code size, and tries to account for any temporaries that are required etc.  I expect what you are seeing whether the definition of "config" is inlined prior to or after "reconciler" is considered for inlining and it won't inline the config.log method unless it can collapse the reference to the property and that won't happen unless reconciler is inlined first.

It could also be that the accounting for the function is incorrect and we are simply missing an opportunity as a result.

If you use --assume_function_wrapper, the compiler will be more aggressive and that may be helpful to you here.

--

---
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-discuss+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/closure-compiler-discuss/1e12da92-0fa9-4646-a258-c4ba77cd7f8c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Manas Jayanth

unread,
Jul 19, 2018, 11:41:44 PM7/19/18
to Closure Compiler Discuss
John,

Appreciate the quick response. I saw your reply the other day quickly tried it out. And you were right. Using --assume_function_wrapper inlined the console.log.

However, the real world code returns an object. So when I tried the following, it stopped inlining again.


(function main() {

  const config = {
    log(m) {
      console.log(m);
    }
  }

  function reconciler(c) {
    const log = c.log;
    log('jere');
    return {
      foo() {
        // More side effects
      }
    }
  }

  reconciler(config);

}())

min.js

(function(a) {
  a = a.log;
  a("jere");
  return { foo: function() {} };
})({
  log: function(a) {
    console.log(a);
  }
});

>  I expect what you are seeing whether the definition of "config" is inlined prior to or after "reconciler" is considered for inlining and it won't inline the config.log method unless it can collapse the reference to the property and that won't happen unless reconciler is inlined first.

Could you please elaborate? TBH, I couldn't follow the sentence. My apologies.
Reply all
Reply to author
Forward
0 new messages