implement name generation & collision avoidance

This commit is contained in:
alexlamsl 2017-10-25 01:53:18 +08:00
parent cf75ccbce9
commit 1282206db3
2 changed files with 73 additions and 56 deletions

View File

@ -2689,6 +2689,10 @@ merge(Compressor.prototype, {
var self = this; var self = this;
if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self; if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self;
var defs_by_id = Object.create(null); var defs_by_id = Object.create(null);
var var_names = Object.create(null);
self.enclosed.forEach(function(def) {
var_names[def.name] = true;
});
var tt = new TreeTransformer(function(node) { var tt = new TreeTransformer(function(node) {
if (node instanceof AST_VarDef) { if (node instanceof AST_VarDef) {
var sym = node.name, def, value; var sym = node.name, def, value;
@ -2699,31 +2703,13 @@ merge(Compressor.prototype, {
&& (value = sym.fixed_value()) === node.value && (value = sym.fixed_value()) === node.value
&& value instanceof AST_Object) { && value instanceof AST_Object) {
var defs = new Dictionary(); var defs = new Dictionary();
var assignments = [ var assignments = [];
make_node(AST_VarDef, node, {
name: sym,
value: make_node(AST_Object, value, {
properties: []
})
})
];
value.properties.forEach(function(prop) { value.properties.forEach(function(prop) {
var key = make_node(sym.CTOR, sym, {
name: make_node(AST_Sub, sym, {
expression: sym,
property: make_node(AST_String, prop, {
value: prop.key
})
}).print_to_string(),
scope: self
});
defs.set(prop.key, self.def_variable(key));
assignments.push(make_node(AST_VarDef, node, { assignments.push(make_node(AST_VarDef, node, {
name: key, name: make_sym(prop.key),
value: prop.value value: prop.value
})); }));
}); });
if (assignments.length == 1) return assignments[0];
defs_by_id[def.id] = defs; defs_by_id[def.id] = defs;
return MAP.splice(assignments); return MAP.splice(assignments);
} }
@ -2739,10 +2725,25 @@ merge(Compressor.prototype, {
scope: node.expression.scope, scope: node.expression.scope,
thedef: def thedef: def
}); });
def.references.push(sym); sym.reference({});
return sym; return sym;
} }
} }
function make_sym(key) {
var prefix = sym.name + "_" + key.replace(/[^a-z_$]+/ig, "_");
var name = prefix;
for (var i = 0; var_names[name]; i++) name = prefix + "$" + i;
var new_var = make_node(sym.CTOR, sym, {
name: name,
scope: self
});
var def = self.def_variable(new_var);
defs.set(key, def);
self.enclosed.push(def);
var_names[name] = true;
return new_var;
}
}); });
return self.transform(tt); return self.transform(tt);
}); });

View File

@ -7,9 +7,6 @@ issue_2377_1: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var obj = { var obj = {
foo: 1, foo: 1,
@ -24,10 +21,10 @@ issue_2377_1: {
console.log(obj.foo, obj.cube(3)); console.log(obj.foo, obj.cube(3));
} }
expect: { expect: {
var n = 1, o = function(n) { var obj_foo = 1, obj_cube = function(x) {
return n * n * n; return x * x * x;
}; };
console.log(n, o(3)); console.log(obj_foo, obj_cube(3));
} }
expect_stdout: "1 27" expect_stdout: "1 27"
} }
@ -42,9 +39,6 @@ issue_2377_2: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var obj = { var obj = {
foo: 1, foo: 1,
@ -59,8 +53,8 @@ issue_2377_2: {
console.log(obj.foo, obj.cube(3)); console.log(obj.foo, obj.cube(3));
} }
expect: { expect: {
console.log(1, function(n) { console.log(1, function(x) {
return n * n * n; return x * x * x;
}(3)); }(3));
} }
expect_stdout: "1 27" expect_stdout: "1 27"
@ -76,9 +70,6 @@ issue_2377_3: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var obj = { var obj = {
foo: 1, foo: 1,
@ -105,9 +96,6 @@ direct_access_1: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var a = 0; var a = 0;
var obj = { var obj = {
@ -119,12 +107,12 @@ direct_access_1: {
} }
expect: { expect: {
var a = 0; var a = 0;
var o = { var obj = {
a: 1, a: 1,
b: 2, b: 2,
}; };
for (var r in o) a++; for (var k in obj) a++;
console.log(a, o.a); console.log(a, obj.a);
} }
expect_stdout: "2 1" expect_stdout: "2 1"
} }
@ -136,9 +124,6 @@ direct_access_2: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var o = { a: 1 }; var o = { a: 1 };
var f = function(k) { var f = function(k) {
@ -147,9 +132,9 @@ direct_access_2: {
console.log(f("a")); console.log(f("a"));
} }
expect: { expect: {
var n = { a: 1 }; var o = { a: 1 };
console.log(function(o) { console.log(function(k) {
if (n[o]) return "PASS"; if (o[k]) return "PASS";
}("a")); }("a"));
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@ -162,18 +147,15 @@ direct_access_3: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var o = { a: 1 }; var o = { a: 1 };
o.b; o.b;
console.log(o.a); console.log(o.a);
} }
expect: { expect: {
var a = { a: 1 }; var o = { a: 1 };
a.b; o.b;
console.log(a.a); console.log(o.a);
} }
expect_stdout: "1" expect_stdout: "1"
} }
@ -185,9 +167,6 @@ single_use: {
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
mangle = {
toplevel: true,
}
input: { input: {
var obj = { var obj = {
bar: function() { bar: function() {
@ -204,3 +183,40 @@ single_use: {
}.bar()); }.bar());
} }
} }
name_collision: {
options = {
reduce_vars: true,
hoist_props: true,
toplevel: true,
}
input: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj = {
foo: 3,
bar: 4,
"b-r": 5,
"b+r": 6,
"b!r": 7,
};
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
}
f();
}
expect: {
var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj_foo$0 = 3,
obj_bar = 4,
obj_b_r = 5,
obj_b_r$0 = 6,
obj_b_r$1 = 7;
console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);
}
f();
}
expect_stdout: "1 3 4 5 6 7"
}