Skip to content

Commit

Permalink
mangle global variable as global object property
Browse files Browse the repository at this point in the history
closes #5933
  • Loading branch information
alexlamsl committed Sep 6, 2024
1 parent b54f298 commit 2a05aa2
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 2 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ a double dash to prevent input files being used as option arguments:
`debug` Add debug prefix and suffix.
`domprops` Mangle property names that overlaps
with DOM properties.
`globals` Mangle variable access via global object.
`keep_quoted` Only mangle unquoted properties.
`regex` Only mangle matched property names.
`reserved` List of names that should not be mangled.
Expand Down Expand Up @@ -293,6 +294,9 @@ var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log
In order for this to be of any use, we avoid mangling standard JS names by
default (`--mangle-props builtins` to override).

Specify `--mangle-props globals` to mangle property names of global
object (e.g. `self.foo`) as global variables.

A default exclusion file is provided in `tools/domprops.json` which should
cover most standard JS and DOM properties defined in various browsers. Pass
`--mangle-props domprops` to disable this feature.
Expand Down Expand Up @@ -902,6 +906,9 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
- `domprops` (default: `false`) — Use `true` to allow the mangling of properties
commonly found in Document Object Model. Not recommended to override this setting.

- `globals` (default: `false`) — Use `true` to mangle properties of global object
alongside undeclared variables.

- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
arguments.

Expand Down
32 changes: 30 additions & 2 deletions lib/propmangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,16 @@ function mangle_properties(ast, options) {
cache: null,
debug: false,
domprops: false,
globals: false,
keep_quoted: false,
regex: null,
reserved: null,
}, true);

var is_global = options.globals ? function(prop_access) {
var exp = prop_access.expression;
return exp instanceof AST_SymbolRef && exp.definition().undeclared;
} : return_false;
var reserved = options.builtins ? new Dictionary() : get_builtins();
if (!options.domprops && typeof domprops !== "undefined") domprops.forEach(function(name) {
reserved.set(name, true);
Expand Down Expand Up @@ -225,9 +230,17 @@ function mangle_properties(ast, options) {
add(node.key);
}
} else if (node instanceof AST_Dot) {
if (is_lhs(node, this.parent())) add(node.property);
if (is_global(node)) {
add_global(node.property);
} else if (is_lhs(node, this.parent())) {
add(node.property);
}
} else if (node instanceof AST_Sub) {
if (is_lhs(node, this.parent())) addStrings(node.property, add);
if (is_global(node)) {
addStrings(node.property, add_global);
} else if (is_lhs(node, this.parent())) {
addStrings(node.property, add);
}
}
}));

Expand Down Expand Up @@ -292,6 +305,21 @@ function mangle_properties(ast, options) {
if (!should_mangle(name)) unmangleable.set(name, true);
}

function add_global(name) {
add(name);
if (!should_mangle(name)) return;
var def = ast.globals.get(name);
if (!def) return;
var opts = Object.create(options);
opts.reserved = reserved.map(function(_, name) {
return name;
});
def.unmangleable = return_false;
def.mangle(_default_mangler_options(opts));
delete def.unmangleable;
cache.set(name, def.mangled_name || name);
}

function mangle(name) {
if (!should_mangle(name)) return name;
var mangled = cache.get(name);
Expand Down
119 changes: 119 additions & 0 deletions test/compress/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,125 @@ accessor_this: {
expect_stdout: "1 2 2"
}

keep_global_property: {
mangle = {
properties: {
globals: false,
}
}
input: {
foo = "PASS";
global.foo = "FAIL";
console.log(foo);
}
expect: {
foo = "PASS";
global.o = "FAIL";
console.log(foo);
}
}

mangle_global_property_1: {
mangle = {
properties: {
globals: true,
}
}
input: {
foo = "PASS";
console.log(global.foo);
}
expect: {
o = "PASS";
console.log(global.o);
}
expect_stdout: "PASS"
}

mangle_global_property_2: {
mangle = {
properties: {
globals: true,
}
}
input: {
foo = "FAIL";
global.foo = "PASS";
console.log(foo);
}
expect: {
o = "FAIL";
global.o = "PASS";
console.log(o);
}
expect_stdout: "PASS"
}

mangle_global_property_3: {
mangle = {
properties: {
globals: true,
}
}
options = {
// sandbox quirk
toplevel: true,
}
input: {
var foo = "PASS";
global.foo = "FAIL";
console.log(foo);
}
expect: {
var foo = "PASS";
global.o = "FAIL";
console.log(foo);
}
expect_stdout: "PASS"
}

mangle_global_property_4: {
mangle = {
properties: {
globals: true,
}
}
input: {
o = "foo";
A = "bar";
global.A = "baz";
console.log(o, A);
}
expect: {
o = "foo";
l = "bar";
global.l = "baz";
console.log(o, l);
}
expect_stdout: "foo baz"
}

mangle_global_property_5: {
mangle = {
properties: {
globals: true,
}
}
input: {
var o = "foo";
A = "bar";
global.A = "baz";
console.log(o, A);
}
expect: {
var o = "foo";
l = "bar";
global.l = "baz";
console.log(o, l);
}
expect_stdout: "foo baz"
}

issue_2208_1: {
options = {
inline: true,
Expand Down

0 comments on commit 2a05aa2

Please sign in to comment.