简体   繁体   English

打字稿和谷歌关闭

[英]Typescript and Google Closure

I use Typescript command (tsc) to create a single Javascript file containing all plateform classes. 我使用Typescript命令(tsc)创建一个包含所有平台类的Javascript文件。

tsc "./Main.ts" -out "./script/myProject_debug.js" --declarations

Then, I want to obfuscate this file with Google Closure (compiler.jar) like this : 然后,我想用Google Closure(compiler.jar)来混淆这个文件,如下所示:

java -jar ./compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js "./script/myProject_debug.js" > "./script/myProject.js".

But when I execute the resulting obfuscated/optimized code, I got this following error : Uncaught TypeError: Cannot read property 'prototype' of undefined 但是当我执行生成的混淆/优化代码时,我得到以下错误:Uncaught TypeError:无法读取未定义的属性'prototype'

Which matches the following non-obfuscated JS code (generated by tsc command) : 它匹配以下非混淆的JS代码(由tsc命令生成):

var __extends = this.__extends || function (d, b) {
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
}

This part is used to translate the "extends" Typescript keyword and the equivalent of b is undefined. 这部分用于翻译“extends”Typescript关键字,而b的等价物是未定义的。

Is anyone got similar error or/and get a solution to be able to obfuscate with Google Closure with a Typescript compiled file? 是否有人有类似的错误或/并获得一个解决方案,能够使用Typescript编译文件与谷歌闭包混淆?

I tried with uglifyjs command and the output file works perfectly, but I want total obfuscation (classes, args, variables, methods, etc). 我尝试使用uglifyjs命令并且输出文件完美地工作,但我想要完全混淆(类,参数,变量,方法等)。 Also, the extra optimization provided by Google Closure would be welcome. 此外,Google Closure提供的额外优化将受到欢迎。

Thanks you! 谢谢!

The definition of __extends has an issue which is most likely causing the error you see. __extends的定义有一个问题很可能导致您看到的错误。

var __extends = this.__extends || function (d, b) { ... };

The this.__extends reference is meant to be the same thing as window.__extends , however Closure-compiler does not know (or ever even tries) to realize that the reference to this in the global context is in fact the window object. this.__extends引用意味着与window.__extends相同,但Closure-compiler不知道(或甚至尝试)实现在全局上下文中对this的引用实际上是window对象。 Compiled with --warning_level=VERBOSE the compiler will emit the warning: 使用--warning_level=VERBOSE编译编译器将发出警告:

Dangerous use of the global this object at line 1 character 16
var __extends = this.__extends || function (d, b) {
                ^

In addition, the this.__extends is a reference to an external/undefined property and the compiler is also warning about that on VERBOSE level. 另外, this.__extends是对外部/未定义属性的引用,编译器也在VERBOSE级别上警告它。

I've modified and annotated the definition to compile without warnings using the Closure-compiler Service UI : 我使用Closure-compiler Service UI修改并注释了要编译的定义而没有警告:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @warning_level VERBOSE
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

var __extends = window['__extends'] || function (d, b) {
  /** @constructor */
  function __() { this.constructor = d; }
  __.prototype = b.prototype;
  d.prototype = new __();
}

/**
 * @constructor
 * @extends {String}
 */
function foo2() {this.foo = 'bar'; }
__extends(foo2, String);

var bar2 = new foo2;
alert(bar2.toLowerCase);

A JSFiddle of the modified and compiled code 修改和编译代码的JSFiddle

Ok I found the problem. 好的我发现了问题。

As I said earlier, b is undefined in : 正如我之前所说,b未定义为:

var __extends = this.__extends || function (d, b) {
   function __() { this.constructor = d; }
   __.prototype = b.prototype;
   d.prototype = new __();
}

When typescript "compile" into javascript, if you got one namespace by project but that you write all classes related to this namespace in separated files, Typescript do the following in the final generated js file : 当typescript“编译”成javascript时,如果你有一个项目命名空间,但你在分离的文件中编写了与这个命名空间相关的所有类,那么Typescript会在最终生成的js文件中执行以下操作:

var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1 = Class1;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2 = Class2;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

I don't know exactly how its works but somewhere google-closure-compiler removed some classes even if there is no problem with this code and JS can handle it. 我不确切知道它是如何工作的,但某些地方google-closure-compiler删除了一些类,即使这个代码没有问题,JS也可以处理它。 So some dependencies was missing and b was undefined. 因此缺少某些依赖项,而b未定义。

So I found that if you declare your namespace like the following, you will not encounter the error anymore (closure will keep all your classes in the final obfuscated js file as long as the "Main" class is used or that you keep a reference of your namespace in the global window object) : 所以我发现如果你声明你的命名空间如下,你就不会再遇到错误了(只要使用了“Main”类,或者你保留了一个引用,闭包会将你所有的类保留在最终的混淆js文件中您在全局窗口对象中的命名空间):

var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1= Class1;

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2= Class2;

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

I think I will open an issue on typescriptlang.org. 我想我会在typescriptlang.org上打开一个问题。 It's optimizing the generated file size by the way. 它正在优化生成的文件大小。

Thank you for your answers! 谢谢您的回答!

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

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