3

I am planning on obfuscating my js code for this project.
I have multiple js files that I am planning on combining to one minified, obfuscated js file.

Now the question is, is there a way to change the HTML calls (such as onClick) to the obfuscated function names?

** example:

assume file main.js before obfuscation

function functionName(){
 //Do Something here
}

and assume index.html as follows:

...
<button onClick="functionName()">    

...

<script src="path/to/file/main.js"></script>    
...

now file main.js after obfuscation and minification:

function a(){//Do Something here}

now I need index.html to call that function, is there a way to automate change of the onclick call from functionName() to a() during the obfuscation process in the index.html file??

*** end example

if not, after everything is minified and obfuscated, how would I change it manually?

*Side note, right now I am considering using google's closure compiler.

Baruch
  • 1,618
  • 5
  • 23
  • 42
  • you edit the original file and minify it again – slashsharp Nov 12 '16 at 05:14
  • @slashsharp could you kindly elaborate a little? This is my first time tackling minification and obfuscation, once the code is minified and obfuscated, wouldn't it be almost impossible to read? and do you mean the original js file? – Baruch Nov 12 '16 at 05:17
  • How important is it that the function names be obfuscated? If you're not worried about the names of the functions, than Closure Compiler has both `externs` and `export`s which support what you're asking for. https://developers.google.com/closure/compiler/docs/api-tutorial3#export – Graham P Heath Nov 13 '16 at 17:11

3 Answers3

3

Don't use inline attributes like onclick to bind events.

Bind events in Javascript code, using EventTarget.addEventListener(), e.g. instead of:

<button id="myButton" onClick="somefunction()">

leave out the onClick attribute and run the following after page load:

document.getElementById("myButton").addEventListener("click", somefunction);

Note that, if you're using a library like jQuery, it'll probably provide you with cleaner ways of doing this, e.g.

$("#myButton").on("click", somefunction);
  • I was thinking of that, however I am dealing with `handlebars.js` and I change to content of the page using templates. I noted, at least from previous experience, that some jquery "on" calls and such tend to not work since most elements, except first page, are not loaded into DOM immediately. Is there a way around this? easiest (and dirtiest) way I found was using onclick html attribute. – Baruch Nov 12 '16 at 06:17
  • You need to delay those calls until the document is loaded. If using jQuery, wrap them in `$(function(){ … })`. Otherwise, see: http://stackoverflow.com/questions/9899372/pure-javascript-equivalent-to-jquerys-ready-how-to-call-a-function-when-the –  Nov 12 '16 at 06:53
  • thanks for the link, but would handlebars.js templates that haven't been submitted to the page's html yet work with this technique? I believe I have tried something similar before to no avail. I am changing the div's inner html on the fly when needed therefore they are only then loaded into the DOM and on calls are not effective on it. – Baruch Nov 12 '16 at 06:59
  • If you're injecting new markup after your page has loaded, you'll need to bind any events to the new elements when that happens. –  Nov 12 '16 at 08:48
0

With Google Closure Compiler you could perhaps write your own tool to read Source Maps which compiler options like --create_source_map create.

If you look at the design doc referenced on that page you will see this example of the source map output:

{
"version" : 3,
"file": "out.js",
"sourceRoot": "",
"sources": ["foo.js", "bar.js"],
"sourcesContent": [null, null],
"names": ["src", "maps", "are", "fun"],
"mappings": "A,AAAB;;ABCDE;"
}

The last two lines show that src became A, and maps became AAAB, etc.

You could use the source map to find what the compiler renamed your function to, and then modify index.html accordingly.

However, the way this is usually handled is to instead tell the compiler to not rename functionName. (The code within functionName will still be minimized.) There are various ways to do this such as using the @export tag

/**
* @export
* @return {undefined}
*/
function functionName(){
 //Do Something here
}

Alternatively you can use goog.exportSymbol or goog.exportProperty directly (which is what the @export tag generates). There is more information on this page about exporting symbols https://developers.google.com/closure/compiler/docs/api-tutorial3?csw=1


previous answer

The functions (properties, and other names) that are built-in to the browser and JavaScript cannot be minified because then the browser/JavaScript won't recognize what you are trying to do. onclick is one of those built-in properties of an HTMLElement.

You can obfuscate the function you assign to onclick but not the name onclick itself.

As another example, you can't minify JavaScript keywords like function, this, return.

owler
  • 1,059
  • 8
  • 13
0

This can be done, but I don't know of any automated tools to do it (unless you are using Polymer). The higher the level of obfuscation, the harder this becomes.

Closure-Compiler SIMPLE Optimizations

Use the --variable_renaming_report flag to output a map of renamed variables. In SIMPLE mode, properties will not be renamed. You can then use this report to rename your symbols in HTML. Parse5 is a great tool for parsing and walking through a DOM tree and can assist in this.

Closure-Compiler ADVANCED Optimizations

In this mode, the only way to safely accomplish this is with a multi-step process. And it's quite involved. You need to transform the references from the HTML into fake javascript, pass that fake javascript into closure-compiler along with your source and use the module flags to split the output, then post process the renamed output of the compiler and update the original HTML. This is the methodology used by Polymer-Rename.

Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57