I use Typescript command (tsc) to create a single Javascript file containing all plateform classes.
tsc "./Main.ts" -out "./script/myProject_debug.js" --declarations
Then, I want to obfuscate this file with Google Closure (compiler.jar) like this :
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
Which matches the following non-obfuscated JS code (generated by tsc command) :
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.
Is anyone got similar error or/and get a solution to be able to obfuscate with Google Closure with a Typescript compiled file?
I tried with uglifyjs command and the output file works perfectly, but I want total obfuscation (classes, args, variables, methods, etc). Also, the extra optimization provided by Google Closure would be welcome.
Thanks you!
The definition of
__extends
has an issue which is most likely causing the error you see.The
this.__extends
reference is meant to be the same thing aswindow.__extends
, however Closure-compiler does not know (or ever even tries) to realize that the reference tothis
in the global context is in fact thewindow
object. Compiled with--warning_level=VERBOSE
the compiler will emit the warning:In addition, the
this.__extends
is a reference to an external/undefined property and the compiler is also warning about that onVERBOSE
level.I've modified and annotated the definition to compile without warnings using the Closure-compiler Service UI:
A JSFiddle of the modified and compiled code
Ok I found the problem.
As I said earlier, b is undefined in :
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 :
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. So some dependencies was missing and b was undefined.
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) :
I think I will open an issue on typescriptlang.org. It's optimizing the generated file size by the way.
Thank you for your answers!