首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有没有办法告诉Google闭包编译器*而不是*内联我的本地函数?

有没有办法告诉Google闭包编译器*而不是*内联我的本地函数?
EN

Stack Overflow用户
提问于 2016-04-29 05:07:33
回答 2查看 938关注 0票数 0

,这是我要找的:

  • 我希望在禁用一个特定功能(禁用本地函数内联)的同时,使用简单模式小型化的出色功能。
  • 更新:答案是否定的,考虑到我的设置,这是不可能的。但是对于我来说,如果我使用Grails,就有一个解决办法。
  • 正如@乍得在下文所解释的那样,“这违反了编译器的核心假设”。有关更多信息,请参见下面的UPDATE3。

有疑问的形式:

  • 我使用的是CompilationLevel.SIMPLE_OPTIMIZATIONS,它可以完成我想做的任何事情,除了它在内联我的本地函数。
  • 有办法绕过这件事吗?例如,我是否可以在JS文件中设置一个设置,告诉Google闭包不要内联我的本地函数?

在我的javascript文件的顶部有一些指令是很酷的,例如:

代码语言:javascript
运行
复制
// This is a JS comment...
// google.closure.compiler = [inlineLocalFunctions: false]

我正在开发一个Grails应用程序并使用Grails资产管道插件,它使用Google闭包编译器(以下简称Compiler)。该插件支持编译器通过Grails配置grails.assets.minifyOptions支持的不同的小型化级别。这允许‘简单’,‘高级’,‘白空间_只’。

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

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

因此,通过使用资产管道的“简单”设置,本地函数正在内联,这给我带来了麻烦。示例: ExtJS ext-all-debug.js,它使用大量的本地函数。

因此,post 某些功能?提供了一些帮助。我可以使用它的window['dontBlowMeAway'] = dontBlowMeAway技巧来防止我的函数内联。然而,我有很多函数,我不打算手动为每一个函数这样做;我也不想为自己编写一个脚本。创建JS模型并试图标识本地函数听起来既不安全,也不有趣,也不快。

前面的SO将读者引导到https://developers.google.com/closure/compiler/docs/api-tutorial3#removal,在那里解释了window['bla']技巧,并且可以工作。

哇谢谢你读了这么长时间。

帮助?:-)

UPDATE1:

好吧。虽然花了所有的精力写这个问题,我可能有一个技巧,可以工作。Grails使用Groovy。Groovy使用它的MetaClass API使方法调用拦截变得容易。

我将尝试拦截以下电话:

代码语言:javascript
运行
复制
com.google.javascript.jscomp.Compiler.compile(
    List<T1> externs, List<T2> inputs, CompilerOptions options)

我的拦截方法如下所示:

代码语言:javascript
运行
复制
options.inlineLocalFunctions=false
// Then delegate call to the real compile() method

现在是睡觉时间了,我以后再试这个。即便如此,在没有黑客攻击的情况下解决这个问题还是很好的。

UPDATE2:在类似帖子(某些功能?)中的响应并不能解决我的问题,因为我需要大量的内联函数。我已经解释过这一点了。

以我前面提到的ExtJS文件为例,说明为什么上面的类似的SO不能解决我的问题。查看ext-all-debug.js的原始代码。查找byAttribute()函数。然后继续查找字符串"byAttribute“,您将看到它是正在定义的字符串的一部分。我不熟悉这段代码,但我假设这些基于字符串的byAttribute值稍后将传递给JS()函数执行。当byAttribute是字符串的一部分时,编译器不会改变它的这些值。一旦function byAttribute内联,调用函数的尝试就不再可能了。

UPDATE3: I尝试了两种策略来解决这个问题,但都失败了。然而,我成功地实现了一个解决方案。我的尝试失败了

  1. 使用Groovy方法拦截( method,又名MOP)来拦截com.google.javascript.jscomp.Compiler.compile()
  2. 分叉闭包编译器. the (创建我自己的自定义副本),并通过设置com.google.javascript.jscomp.applySafeCompilationOptions()而不是本地设置来修改options.setInlineFunctions(Reach.NONE);

方法拦截不起作用,因为Compiler.compile()是一个被标记为@CompileStatic的Groovy类调用的Java类。这意味着在process()调用谷歌的Compiler.compile()时不使用Groovy的拖把。即使是ClosureCompilerProcessor.translateMinifyOptions() (Groovy代码)也不能被拦截,因为类是@CompileStatic。唯一能被拦截的方法是ClosureCompilerProcessor.process()

分叉谷歌的闭包编译器. was是我最后丑陋的选择。但是就像@Chad在下面所说的,简单地在正确的位置插入options.setInlineFunctions(Reach.NONE)并没有复活我的内联JS函数名。我试图切换其他选项,如setRemoveDeadCode=false,但没有结果。我意识到查德说的没错。我最终会翻转周围的设置,并可能破坏小型化的工作方式。

我的解决方案:,我用UglifyJS预压缩了ext-all调试器,并将它们添加到我的项目中。我本可以将文件命名为ext-all-debug.min.js,以使其更清晰,但我没有这样做。下面是我在Grails Config.groovy中放置的设置:

代码语言:javascript
运行
复制
grails.assets.minifyOptions = [
    optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED
]

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

好了。问题解决了。

关键词:小型化,小型化,丑陋,UglifyJS,UglifyJS2

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-01 17:32:02

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

然而-禁用内联是不够的,以确保这一安全。重命名和死代码消除也会导致问题。这违反了编译器的核心假设。此本地函数仅从字符串中引用。

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

票数 2
EN

Stack Overflow用户

发布于 2018-04-11 19:57:05

使用函数构造函数

代码语言:javascript
运行
复制
var fnc = new Function("param1", "param2", "alert(param1+param2);");

闭包将使字符串文本不受影响。

请参阅对象/功能

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36929970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档