没有全局命名空间污染的Haxe JavaScript?

9

这个问题仅适用于Haxe版本< 2.10

我知道Haxe已经有一段时间了,但直到昨天我才真正开始使用它。好奇心驱使下,我决定将showdown.js(一个markdown.pl的JavaScript端口)移植到Haxe。这很简单,生成的JavaScript代码似乎也可以正常运行(编辑:如果您想看到它的实际效果,请在这里查看)。

然而,我注意到生成的代码在全局命名空间中倾泻了大量的内容...更糟糕的是,它通过给未声明的标识符赋值而不使用var关键字来实现,因此即使您用闭包将整个代码包装起来,它们也是全局的。

例如...

if(typeof js=='undefined') js = {}
...
Hash = function(p) { if( p === $_ ) return; {
...
EReg = function(r,opt) { if( r === $_ ) return; {
...

我使用sed清理了大部分内容,但我还被这样的东西所困扰:

{
 String.prototype.__class__ = String;
 String.__name__ = ["String"];
 Array.prototype.__class__ = Array;
 Array.__name__ = ["Array"];
 Int = { __name__ : ["Int"]}
 Dynamic = { __name__ : ["Dynamic"]}
 Float = Number;
 Float.__name__ = ["Float"];
 Bool = { __ename__ : ["Bool"]}
 Class = { __name__ : ["Class"]}
 Enum = { }
 Void = { __ename__ : ["Void"]}
}
{
 Math.__name__ = ["Math"];
 Math.NaN = Number["NaN"];
 Math.NEGATIVE_INFINITY = Number["NEGATIVE_INFINITY"];
 Math.POSITIVE_INFINITY = Number["POSITIVE_INFINITY"];
 Math.isFinite = function(i) {
  return isFinite(i);
 }
 Math.isNaN = function(i) {
  return isNaN(i);
 }
}

这是一些相当不良的javascript代码。


问题

是否有一个不污染全局变量的haxe分支或克隆版本?修改haxe源代码以获得所需内容是否值得,或者已经有人解决了这个问题?谷歌搜索并没有找到太多相关信息。我愿意听取任何建议。同时,我也很想看看这个东西将会生成什么样的PHP代码... :D


答案?

以下是我尝试过的一些想法:

后处理

这是我的构建脚本;它可以很好地剥离掉一些东西,但并不能捕捉到所有的内容。我不想删除内置构造函数原型的修改;我确信那会导致一些问题。修复所有问题可能是一项艰巨的任务,如果已经有人完成了这项工作,我不想再去做...

haxe -cp ~/Projects/wmd-new -main Markdown -js markdown.js

echo "this.Markdown=(function(){ var \$closure, Float;" > markdown.clean.js;

sed "s/^if(typeof js=='undefined') js = {}$/if(typeof js=='undefined') var js = {};/g ;
     s/^\([ \x09]*\)\([\$_a-zA-Z0-9]* = \({\|function\)\)/\1var \2/g ;
      /^[ \x09]*\(else \)\?null;$/d ;
     " markdown.js >> markdown.clean.js

echo "return Markdown}());" >> markdown.clean.js;

java -jar closure/compiler.jar --js markdown.clean.js \
--compilation_level SIMPLE_OPTIMIZATIONS \
> markdown.cc.js

--js-namespace开关救了我的一天

感谢Dean Burge指出了命名空间开关。这基本上解决了我的问题,只需要很少的帮助就可以。这是我当前的构建脚本。我认为它可以捕获所有全局变量...

NS=N\$

haxe -cp ~/Projects/wmd-new -main Markdown --js-namespace $NS -js markdown.js 

# export our function and declare some vars
echo "this.markdown=(function(){var \$_,\$Main,\$closure,\$estr,js,"$NS"" > markdown.clean.js;

# strip silly lines containing "null;" or "else null;"
sed "/^[ \x09]*\(else \)\?null;$/d ;" markdown.js >> markdown.clean.js

# finish the closure
echo "return "$NS".Markdown.makeHtml}());" >> markdown.clean.js;

这个问题自Haxe 2.10以后就不再相关了。请尝试访问http://try.haxe.org/#1cf90。 - César Alforde
@CésarAlforde 为什么这个问题不再相关了? - Anderson Green
因为自 Haxe 2.10 版本以来所有生成的代码都被封装在一个匿名函数中,所以没有全局命名空间污染,这与使用 Coffeescript 脚本得到的结果是相同的。 - César Alforde
4个回答

7

这个已经解决了我所关心的大部分问题。还有一些未声明的全局变量在浮动; $_, $Main, $closure, $estr, js和用户定义的命名空间是我发现的。这可以通过在闭合的开始处声明变量来轻松解决。 - Dagg Nabbit
我刚刚发现有人为此提交了一个错误报告:http://code.google.com/p/haxe/issues/detail?id=214 - Andy Li

3
Haxe并不适用于在javascript web应用程序中编写孤立的可重用组件。这一点可以从编译器为每个该死的编译过程发出标准库的事实得到证明。最优化javascript目标的使用方式是完全使用Haxe编写应用程序,并使用未经类型定义的块调用外部内容,希望它不会破坏任何东西。您应该像处理Flash片段一样处理Haxe输出,忽略它运行的环境,假设它是唯一运行的东西。
或者,您可以尝试使用with()块包装代码。

谢谢回复。如果我不写一个独立的可重用组件,那么在我看来,我就是在写垃圾。不过我还有一些想法。顺便说一下,我对 with 块的事情笑了...希望那只是个玩笑 :) - Dagg Nabbit
1
顺便提一下,haxetacy有一个后编译器,可以将类分割成文件:http://code.google.com/p/haxetacy/wiki/postcompiler - Andy Li
我不想将它们拆分成文件,我只想避免任何我没有明确导出的全局变量。 - Dagg Nabbit

2

看了一下,但我不确定这是否是我想要的... 不过还是谢谢。 - Dagg Nabbit

1

JSTM JavaScript生成器宏在许多方面优化haxe输出:

  1. JavaScript输出根据类型分为不同的文件。
  2. 这些文件已经被优化。
  3. 加载程序脚本异步加载所需的类型。
  4. 只使用一个全局变量:jstm。
  5. 只下载实际运行您的应用程序所需的代码。
  6. 可以在运行时加载新的类型,从而实现高度可扩展的应用程序。

更多信息请访问http://code.google.com/p/jstm/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接