Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private properties could be better compressed with property mangling #5937

Closed
AshleyScirra opened this issue Sep 16, 2024 · 0 comments · Fixed by #5944
Closed

Private properties could be better compressed with property mangling #5937

AshleyScirra opened this issue Sep 16, 2024 · 0 comments · Fixed by #5944

Comments

@AshleyScirra
Copy link
Contributor

This is a case of sub-optimal but correct code, which the template says is not a bug, so I guess this is a feature request.

Uglify version (uglifyjs -V) 3.19.3

JavaScript input

It's quite long so expand the below:

input.js
const o = {
	prop1: 0,
	prop2: 0,
	prop3: 0,
	prop4: 0,
	prop5: 0,
	prop6: 0,
	prop7: 0,
	prop8: 0,
	prop9: 0,
	prop10: 0,
	prop11: 0,
	prop12: 0,
	prop13: 0,
	prop14: 0,
	prop15: 0,
	prop16: 0,
	prop17: 0,
	prop18: 0,
	prop19: 0,
	prop20: 0,
	prop21: 0,
	prop22: 0,
	prop23: 0,
	prop24: 0,
	prop25: 0,
	prop26: 0,
	prop27: 0,
	prop28: 0,
	prop29: 0,
	prop30: 0,
	prop31: 0,
	prop32: 0,
	prop33: 0,
	prop34: 0,
	prop35: 0,
	prop36: 0,
	prop37: 0,
	prop38: 0,
	prop39: 0,
	prop40: 0,
	prop41: 0,
	prop42: 0,
	prop43: 0,
	prop44: 0,
	prop45: 0,
	prop46: 0,
	prop47: 0,
	prop48: 0,
	prop49: 0,
	prop50: 0,
	prop51: 0,
	prop52: 0,
	prop53: 0,
	prop54: 0,
	prop55: 0,
	prop56: 0,
	prop57: 0,
	prop58: 0,
	prop59: 0,
	prop60: 0
};

class Test {
	public1;
	public2;
	public3;
	#private1;
	#private2;
	#private3;
	
	publicMethod() {}
	#privateMethod() {}
}

Command: uglifyjs input.js --compress --mangle-props --beautify --output output.js

JavaScript output or error produced.

output.js
let o = {
    p: 0,
    o: 0,
    i: 0,
    t: 0,
    l: 0,
    u: 0,
    v: 0,
    h: 0,
    M: 0,
    T: 0,
    g: 0,
    j: 0,
    k: 0,
    m: 0,
    q: 0,
    A: 0,
    B: 0,
    C: 0,
    D: 0,
    F: 0,
    G: 0,
    H: 0,
    I: 0,
    J: 0,
    K: 0,
    L: 0,
    N: 0,
    O: 0,
    P: 0,
    R: 0,
    S: 0,
    U: 0,
    V: 0,
    W: 0,
    X: 0,
    Y: 0,
    Z: 0,
    $: 0,
    _: 0,
    pp: 0,
    rp: 0,
    op: 0,
    ep: 0,
    ip: 0,
    tp: 0,
    lp: 0,
    ap: 0,
    cp: 0,
    bp: 0,
    up: 0,
    vp: 0,
    sp: 0,
    dp: 0,
    hp: 0,
    Mp: 0,
    Tp: 0,
    fp: 0,
    gp: 0,
    jp: 0,
    kp: 0
};

class Test {
    mp;
    np;
    qp;
    #wp;
    #xp;
    #yp;
    zp() {}
    #Ap() {}
}

The key detail is that in class Test, the private properties are mangled to two-letter names. They could instead be one-letter names.

Description
JavaScript's private properties and methods effectively act in a separate namespace to all other properties. They cannot be accessed by string, and they cannot be accessed by any derived or super classes.

Therefore it should always be safe to rename the first private property of a class to a single-letter name like #a. It is impossible for this to have a name collision with anything other than another private property in the same class, and UglifyJS can see all of those in the source.

In our case we have a large and complex codebase which ends up mangling properties to three-letter names. UglifyJS then continues to mangle private properties with three-letter names instead of using shorter one-letter names again. The repro demonstrates this by using enough object properties to push mangled names to two letters, then demonstrates that private properties/methods continue using the same length names instead of taking advantage of the fact they are in a separate namespace and so can use shorter names.

The output code is perfectly valid, just sub-optimal - I'm posting this basically as a feature request, as hopefully it may be a straightforward change to make and a nice win for property mangling code that heavily uses private properties. (It's also ideal if lots of classes use the same private property names like #a as these will also be compressed more effectively.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants