leaningtech / cheerpj-meta

Run Java 8 applications, libraries, applets, Java Web Start, and Oracle Forms on the web without legacy plugins.
https://labs.leaningtech.com/cheerpj
434 stars 21 forks source link

make it possible to use beatified .jar.js files #154

Closed gl91306 closed 1 year ago

gl91306 commented 1 year ago

currently if you use a jar.js file that was compiled directly from cheerpj it works just fine, but if you deobfuscate it it breaks due to how class names are found. In loader.js at the function "cjG" it states:

function cjG(a)
{
    // Centralized handler for all guards
    // Deduce the guard to initialize by code inspection
    var code = a.f.toString();
    var guardPos = 0;
    var pcVal = a.pc | 0;
    if(pcVal < 0)
    {
        var pcVal = -pcVal | 0;
        guardPos = pcVal | 0;
        // Skip until the guard, first "a.pc=-" and ";;if((";
        guardPos = guardPos + 12 | 0;
        while(pcVal)
        {
            guardPos = guardPos + 1 | 0;
            pcVal = pcVal / 10 | 0;
        }
    }
    else
    {
        var pc = "a.pc=" + pcVal + ";;if((";
        guardPos = code.indexOf(pc) + pc.length;
    }
    var endOfGuard = code.indexOf("G|0)", guardPos);
    var mangledClassName = code.substring(guardPos, endOfGuard);
    var cinit=self[mangledClassName + 'X'];
    if(cinit===undefined)
    {
        var cl = null;
        if(cjEnablePreciseClassLoaders){
            var className = cjGetClassName(a.f.name);
            cl = self[className].cl;
            if(cl.hasOwnProperty("cl"))
                cl = cl.cl;
        }
        icjLoadWeakClass(mangledClassName, a, false, cl);
        cinit=self[mangledClassName + 'X'];
    }
    // The guard is called again if continuation are required
    cinit({p:a,f:null,pc:0});
}

Specifically at the lines var pc = "a.pc=" + pcVal + ";;if(("; and var endOfGuard = code.indexOf("G|0)", guardPos);, it shows that it uses obusfcated strings to get the class name. In a debofuscated code the first line would only work with var pc = "a.pc = " + pcVal + ";(\n)if (("; It can be seen that this string finding method should be replaced by using a regex to ignore any amount of spaces so that even "a.pc(big space)=(big space)" would work. It should also accomodate any amount of semicolons and stuff. yeah.

alexp-sssup commented 1 year ago

jar.js files are not intended for human reading or manipulation. The code is optimized for speed and the layout is relevant for multiple internal purposes. As a matter of fact, we are currently working on CheerpJ 3.0 that will require no jar.js files at all.

As a workaround you might be able to use the internal "beautification" from the devtools, but actual support for this is outside the scope of the project.