繁体   English   中英

有没有办法告诉Google Closure编译器*不*内联我的本地函数?

[英]Is there a way to tell Google Closure Compiler to *NOT* inline my local functions?

这是我在寻找的东西:

  • 我想使用SIMPLE模式最小化的出色功能,而仅禁用一项特定功能(禁用内联函数)。


  • 更新:答案是否定的,根据我的设置是不可能的。 但是对我来说,使用Grails有一种解决方法。
  • 正如@Chad在下面解释的那样,“这违反了编译器的核心假设”。 有关更多信息,请参见下面的我的UPDATE3。



问题形式:

  • 我使用的是CompilationLevel.SIMPLE_OPTIMIZATIONS ,它可以执行我想要的所有操作,但它可以内联本地函数。
  • 有没有办法解决? 例如,是否可以在JS文件中放置一个设置,以告知Google Closure不要内联我的本地函数?

在我的javascript文件顶部设置一些指令会很酷,例如:

// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]

我正在开发Grails应用程序并使用Grails资产管道插件,该插件使用Google Closure Compiler(以下称为Compiler)。 该插件通过Grails配置grails.assets.minifyOptions支持Compiler支持的不同缩小级别。 这允许“ SIMPLE”,“ ADVANCED”,“ WHITESPACE_ONLY”。

AssetCompiler.groovy(资产管道插件)调用ClosureCompilerProcessor.process()

最终,在CompilerOptions对象上分配了SIMPLE_OPTIMIZATIONS 这样做,作为副产品, CompilerOptions.inlineLocalFunctions = true (这是Compiler中的硬编码行为)。 如果我要使用WHITESPACE_ONLY则结果为inlineLocalFunctions=false

因此,通过使用Asset Pipeline的“ SIMPLE”设置,内联了本地功能,这给我带来了麻烦。 示例:ExtJS ext-all-debug.js ,它使用许多本地函数。

SO post 是否可以使Google Closure编译器*不*内联某些功能? 提供一些帮助。 我可以使用其window['dontBlowMeAway'] = dontBlowMeAway技巧来防止函数内联。 但是我有很多功能,我不会为每个功能手动进行操作; 我也不想写一个脚本来帮我做。 创建JS模型并尝试标识本地函数听起来并不安全,有趣或快速。

上一则SO文章将读者带到https://developers.google.com/closure/compiler/docs/api-tutorial3#removal ,在该window['bla']中解释了window['bla']技巧,并且该技巧有效。

哇,谢谢您读了这么长时间。

救命? :-)


UPDATE1:

好的。 在花所有的精力写这个问题的同时,我可能会有一个可行的技巧。 Grails使用Groovy。 Groovy使用其MetaClass API使方法调用拦截变得容易。

我将尝试拦截对以下内容的调用:

com.google.javascript.jscomp.Compiler.compile(
    List<T1> externs, List<T2> inputs, CompilerOptions options)

我的拦截方法如下所示:

options.inlineLocalFunctions=false
// Then delegate call to the real compile() method

现在是睡觉时间,所以我以后必须再尝试。 即便如此,解决这个问题也很不错。



UPDATE2:类似帖子中的响应( 是否可以使Google Closure编译器*不*内联某些功能? )由于需要内联的大量功能无法解决我的问题。 我已经解释了这一点。

以我上面引用的ExtJS文件为例,说明上述类似的SO帖子为什么不能解决我的问题。 查看ext-all-debug.js的原始代码。 找到byAttribute()函数。 然后继续寻找字符串“ byAttribute”,您将看到它是正在定义的字符串的一部分。 我对这段代码不熟悉,但我想以后将这些基于字符串的byAttribute值传递给JS的eval()函数来执行。 byAttribute是字符串的一部分时,编译器不会更改byAttribute这些值。 内联function byAttribute ,将无法再尝试调用该函数。



UPDATE3:我尝试了两种策略来解决此问题,但均未成功。 但是,我成功实现了一种解决方法。 我失败的尝试:

  1. 使用Groovy方法拦截(元对象协议,又称MOP)拦截com.google.javascript.jscomp.Compiler.compile()
  2. 通过设置options.setInlineFunctions(Reach.NONE);创建closure-compiler.jar(创建自己的自定义副本)并修改com.google.javascript.jscomp.applySafeCompilationOptions() options.setInlineFunctions(Reach.NONE); 而不是LOCAL。

方法拦截不起作用,因为Compiler.compile()是一个Java类,由标记为@CompileStatic的Groovy类调用。 这意味着当process()调用Google的Compiler.compile()时,不使用Groovy的MOP。 甚至ClosureCompilerProcessor.translateMinifyOptions() (Groovy代码)也无法被拦截,因为该类是@CompileStatic 唯一可以拦截的方法是ClosureCompilerProcessor.process()

分叉谷歌的closures-compiler.jar是我最后的丑陋手段。 但是就像@Chad在下面说的那样,仅在正确的位置插入options.setInlineFunctions(Reach.NONE)并不options.setInlineFunctions(Reach.NONE)我的内联JS函数名称复活。 我尝试将其他选项(例如setRemoveDeadCode=false切换为无效。 我意识到乍得所说的是对的。 我最终会四处翻转设置,并可能破坏缩小的工作方式。

我的解决方案:我用UglifyJS预压缩了ext-all-debug.js并将其添加到我的项目中。 我可以将文件ext-all-debug.min.js命名为更干净,但我没有。 以下是我放置在Grails Config.groovy中的设置:

grails.assets.minifyOptions = [
    optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]

grails.assets.minifyOptions.excludes = [
    '**ext-all-debug.js',
    '**ext-theme-neptune.js'
]

做完了 问题解决了。




关键字:缩小,缩小,uglify,UglifyJS,UglifyJS2

在这种情况下,您将需要对编译器进行自定义构建或使用Java API。

但是-禁用内联不足以使其安全。 重命名和无效代码删除也会引起问题。 这违反了编译器的核心假设。 仅在字符串内引用此局部函数。

此代码仅对编译器的WHITESPACE_ONLY模式安全。

使用函数构造函数

var fnc = new Function("param1", "param2", "alert(param1+param2);");

闭包将不理会String文字。

参见https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM