title: Is there a way to tell Google Closure Compiler to *NOT* inline my local functions?
body: <p><strong>Here's what I'm looking for:</strong></p>
  
  <ul>
  <li><strong>I want to use the wonderful features of SIMPLE mode minification while disabling just one specific feature (disable local function inline).</strong></li>
  </ul>
  
  <p><br/></p>
  
  <ul>
  <li><strong>UPDATE: The answer is NO, it's not possible given my setup.</strong> But for me there is a workaround given I am using Grails.</li>
  <li>As @Chad has explained below, "This violates core assumptions of the compiler". See my UPDATE3 below for more info.</li>
  </ul>
  
  <p><br/></p>
  
  <hr>
  
  <p>IN QUESTION FORM:</p>
  
  <ul>
  <li>I'm using <code>CompilationLevel.SIMPLE_OPTIMIZATIONS</code> which does everything I want, except that it's inlining my local functions.</li>
  <li>Is there any way around this? For example, is there a setting I can place in my JS files to tell Google Closure not to inline my local functions?</li>
  </ul>
  
  <p>It would be cool to have some directives at the top of my javascript file such as:</p>
  
  <pre><code>// This is a JS comment...
  // google.closure.compiler = [inlineLocalFunctions: false]
  </code></pre>
  
  <p>I'm developing a Grails app and using the <a href="https://grails.org/plugin/asset-pipeline" rel="nofollow noreferrer">Grails asset-pipeline</a> plugin, which uses Google Closure Compiler (hereafter, Compiler). The plugin supports the different minification levels that Compiler supports via the Grails config <a href="http://bertramdev.github.io/grails-asset-pipeline/guide/configuration.html" rel="nofollow noreferrer">grails.assets.minifyOptions</a>. This allows for 'SIMPLE', 'ADVANCED', 'WHITESPACE_ONLY'.</p>
  
  <p>AssetCompiler.groovy (asset-pipeline plugin) calls <code>ClosureCompilerProcessor.process()</code></p>
  
  <p>That eventually assigns <code>SIMPLE_OPTIMIZATIONS</code> on the CompilerOptions object. And by doing so, <code>CompilerOptions.inlineLocalFunctions = true</code> as a byproduct (this is hard coded behavior in Compiler). If I were to use <code>WHITESPACE_ONLY</code> the result would be <code>inlineLocalFunctions=false</code>.</p>
  
  <p>So by using Asset Pipeline's 'SIMPLE' setting, local functions are being inlined and that is causing me trouble. Example: ExtJS <a href="https://github.com/bjornharrtell/extjs/blob/4.2.1.883/ext-all-debug.js" rel="nofollow noreferrer">ext-all-debug.js</a> which uses lots of local functions.</p>
  
  <p>SO post <a href="https://stackoverflow.com/questions/4297685/is-it-possible-to-make-google-closure-compiler-not-inline-certain-functions">Is it possible to make Google Closure compiler *not* inline certain functions?</a> provides some help. I can use its <code>window['dontBlowMeAway'] = dontBlowMeAway</code> trick to keep my functions from inlining. However I have LOTS of functions and I'm not about to manually do this for each one; nor would I want to write a script to do it for me. Creating a JS model and trying to identity local functions doesn't sound safe, fun nor fast.</p>
  
  <p>The previous SO post directs the reader to <a href="https://developers.google.com/closure/compiler/docs/api-tutorial3#removal" rel="nofollow noreferrer">https://developers.google.com/closure/compiler/docs/api-tutorial3#removal</a>, where the <code>window['bla']</code> trick is explained, and it works.</p>
  
  <p>Wow thanks for reading this long.</p>
  
  <p>Help? :-)</p>
  
  <hr>
  
  <p><strong>UPDATE1:</strong></p>
  
  <p>Okay. While spending all the effort in writing this question, I may have a trick that could work. Grails uses Groovy. Groovy makes method call interception easy using its MetaClass API.</p>
  
  <p>I'm going to try intercepting the call to:</p>
  
  <pre><code>com.google.javascript.jscomp.Compiler.compile(
      List&lt;T1&gt; externs, List&lt;T2&gt; inputs, CompilerOptions options)
  </code></pre>
  
  <p>My intercepting method will look like:</p>
  
  <pre><code>options.inlineLocalFunctions=false
  // Then delegate call to the real compile() method
  </code></pre>
  
  <p>It's bed time so I'll have to try this later. Even so, it would be nice to solve this without a hack.</p>
  
  <p><br/></p>
  
  <hr>
  
  <p><strong>UPDATE2:</strong>
  The response in a similar post (<a href="https://stackoverflow.com/questions/4297685/is-it-possible-to-make-google-closure-compiler-not-inline-certain-functions">Is it possible to make Google Closure compiler *not* inline certain functions?</a>) doesn't resolve my problem because of the large quantity of functions I need inlined. I've already explained this point.</p>
  
  <p>Take the ExtJS file I cited above as an example of why the above <a href="https://stackoverflow.com/questions/4297685/is-it-possible-to-make-google-closure-compiler-not-inline-certain-functions">similar SO post</a> doesn't resolve my problem. Look at the raw code for <a href="https://raw.githubusercontent.com/bjornharrtell/extjs/4.2.1.883/ext-all-debug.js" rel="nofollow noreferrer">ext-all-debug.js</a>. Find the byAttribute() function. Then keep looking for the string "byAttribute" and you'll see that it is part of strings that are being defined. I am not familiar with this code, but I'm supposing that these string-based values of <code>byAttribute</code> are later being passed to <a href="http://www.w3schools.com/jsref/jsref_eval.asp" rel="nofollow noreferrer">JS's eval()</a> function for execution. Compiler does not alter these values of <code>byAttribute</code> when it's part of a string. Once <code>function byAttribute</code> is inlined, attempts to call the function is no longer possible.</p>
  
  <p><br/></p>
  
  <hr>
  
  <p><strong>UPDATE3:</strong> I attempted two strategies to resolve this problem and both proved unsuccessful. However, I successfully implemented a workaround. My failed attempts:</p>
  
  <ol>
  <li>Use Groovy method interception (Meta Object Protocol, aka MOP) to intercept <code>com.google.javascript.jscomp.Compiler.compile()</code>.</li>
  <li>Fork the closure-compiler.jar (make my own custom copy) and modify <code>com.google.javascript.jscomp.applySafeCompilationOptions()</code> by setting <code>options.setInlineFunctions(Reach.NONE);</code> instead of LOCAL.</li>
  </ol>
  
  <p>Method interception doesn't work because <code>Compiler.compile()</code> is a Java class which is invoked by a Groovy class marked as <code>@CompileStatic</code>. That means Groovy's MOP is not used when <code>process()</code> calls Google's <code>Compiler.compile()</code>. Even <code>ClosureCompilerProcessor.translateMinifyOptions()</code> (Groovy code) can't be intercepted because the class is <code>@CompileStatic</code>. The only method that can be intercepted is <code>ClosureCompilerProcessor.process()</code>.</p>
  
  <p>Forking Google's closure-compiler.jar was my last ugly resort. But just like @Chad said below, simply inserting <code>options.setInlineFunctions(Reach.NONE)</code> in the right place didn't resurrect my inline JS functions names. I tried toggling other options such as <code>setRemoveDeadCode=false</code> to no avail. I realized what Chad said was right. I would end up flipping settings around and probably destroying how the minification works.</p>
  
  <p><strong>My solution:</strong> I pre-compressed ext-all-debug.js with UglifyJS and added them to my project. I could have named the files <code>ext-all-debug.min.js</code> to do it more cleanly but I didn't. Below are the settings I placed in my Grails Config.groovy:</p>
  
  <pre><code>grails.assets.minifyOptions = [
      optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
  ]
  
  grails.assets.minifyOptions.excludes = [
      '**ext-all-debug.js',
      '**ext-theme-neptune.js'
  ]
  </code></pre>
  
  <p>Done. Problem solved.</p>
  
  <p><br/>
  <br/>
  <br/>
  Keywords: minify, minification, uglify, UglifyJS, UglifyJS2</p>