minor consolidations (#2484)

- unique symbol generation
- `unsafe` on `AST_Call`
This commit is contained in:
Alex Lam S.L
2017-11-16 04:37:37 +08:00
committed by GitHub
parent fa7a7c5c5a
commit ebe761cad0

View File

@@ -2778,18 +2778,29 @@ merge(Compressor.prototype, {
return self;
});
AST_Scope.DEFMETHOD("make_var_name", function(prefix) {
var var_names = this.var_names;
if (!var_names) {
this.var_names = var_names = Object.create(null);
this.enclosed.forEach(function(def) {
var_names[def.name] = true;
});
this.variables.each(function(def, name) {
var_names[name] = true;
});
}
prefix = prefix.replace(/[^a-z_$]+/ig, "_");
var name = prefix;
for (var i = 0; var_names[name]; i++) name = prefix + "$" + i;
var_names[name] = true;
return name;
});
AST_Scope.DEFMETHOD("hoist_properties", function(compressor){
var self = this;
if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self;
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
var defs_by_id = Object.create(null);
var var_names = Object.create(null);
self.enclosed.forEach(function(def) {
var_names[def.name] = true;
});
self.variables.each(function(def, name) {
var_names[name] = true;
});
return self.transform(new TreeTransformer(function(node) {
if (node instanceof AST_VarDef) {
var sym = node.name, def, value;
@@ -2829,17 +2840,13 @@ merge(Compressor.prototype, {
}
function make_sym(key) {
var prefix = sym.name + "_" + key.toString().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,
name: self.make_var_name(sym.name + "_" + key),
scope: self
});
var def = self.def_variable(new_var);
defs.set(key, def);
self.enclosed.push(def);
var_names[name] = true;
return new_var;
}
}));
@@ -3408,130 +3415,133 @@ merge(Compressor.prototype, {
self.args.length = last;
}
if (compressor.option("unsafe")) {
if (is_undeclared_ref(exp)) {
switch (exp.name) {
case "Array":
if (self.args.length != 1) {
return make_node(AST_Array, self, {
elements: self.args
}).optimize(compressor);
}
break;
case "Object":
if (self.args.length == 0) {
return make_node(AST_Object, self, {
properties: []
});
}
break;
case "String":
if (self.args.length == 0) return make_node(AST_String, self, {
value: ""
});
if (self.args.length <= 1) return make_node(AST_Binary, self, {
left: self.args[0],
operator: "+",
right: make_node(AST_String, self, { value: "" })
if (is_undeclared_ref(exp)) switch (exp.name) {
case "Array":
if (self.args.length != 1) {
return make_node(AST_Array, self, {
elements: self.args
}).optimize(compressor);
break;
case "Number":
if (self.args.length == 0) return make_node(AST_Number, self, {
value: 0
});
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
expression: self.args[0],
operator: "+"
}).optimize(compressor);
case "Boolean":
if (self.args.length == 0) return make_node(AST_False, self);
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
expression: make_node(AST_UnaryPrefix, self, {
expression: self.args[0],
operator: "!"
}),
operator: "!"
}).optimize(compressor);
break;
}
}
else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
return make_node(AST_Binary, self, {
break;
case "Object":
if (self.args.length == 0) {
return make_node(AST_Object, self, {
properties: []
});
}
break;
case "String":
if (self.args.length == 0) return make_node(AST_String, self, {
value: ""
});
if (self.args.length <= 1) return make_node(AST_Binary, self, {
left: self.args[0],
operator: "+",
right: make_node(AST_String, self, { value: "" })
}).optimize(compressor);
break;
case "Number":
if (self.args.length == 0) return make_node(AST_Number, self, {
value: 0
});
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
expression: self.args[0],
operator: "+"
}).optimize(compressor);
case "Boolean":
if (self.args.length == 0) return make_node(AST_False, self);
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
expression: make_node(AST_UnaryPrefix, self, {
expression: self.args[0],
operator: "!"
}),
operator: "!"
}).optimize(compressor);
break;
} else if (exp instanceof AST_Dot) switch(exp.property) {
case "toString":
if (self.args.length == 0) return make_node(AST_Binary, self, {
left: make_node(AST_String, self, { value: "" }),
operator: "+",
right: exp.expression
}).optimize(compressor);
}
else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
var separator;
if (self.args.length > 0) {
separator = self.args[0].evaluate(compressor);
if (separator === self.args[0]) break EXIT; // not a constant
}
var elements = [];
var consts = [];
exp.expression.elements.forEach(function(el) {
var value = el.evaluate(compressor);
if (value !== el) {
consts.push(value);
} else {
if (consts.length > 0) {
elements.push(make_node(AST_String, self, {
value: consts.join(separator)
}));
consts.length = 0;
break;
case "join":
if (exp.expression instanceof AST_Array) EXIT: {
var separator;
if (self.args.length > 0) {
separator = self.args[0].evaluate(compressor);
if (separator === self.args[0]) break EXIT; // not a constant
}
var elements = [];
var consts = [];
exp.expression.elements.forEach(function(el) {
var value = el.evaluate(compressor);
if (value !== el) {
consts.push(value);
} else {
if (consts.length > 0) {
elements.push(make_node(AST_String, self, {
value: consts.join(separator)
}));
consts.length = 0;
}
elements.push(el);
}
elements.push(el);
}
});
if (consts.length > 0) {
elements.push(make_node(AST_String, self, {
value: consts.join(separator)
}));
}
if (elements.length == 0) return make_node(AST_String, self, { value: "" });
if (elements.length == 1) {
if (elements[0].is_string(compressor)) {
return elements[0];
}
return make_node(AST_Binary, elements[0], {
operator : "+",
left : make_node(AST_String, self, { value: "" }),
right : elements[0]
});
}
if (separator == "") {
var first;
if (elements[0].is_string(compressor)
|| elements[1].is_string(compressor)) {
first = elements.shift();
} else {
first = make_node(AST_String, self, { value: "" });
if (consts.length > 0) {
elements.push(make_node(AST_String, self, {
value: consts.join(separator)
}));
}
return elements.reduce(function(prev, el){
return make_node(AST_Binary, el, {
if (elements.length == 0) return make_node(AST_String, self, { value: "" });
if (elements.length == 1) {
if (elements[0].is_string(compressor)) {
return elements[0];
}
return make_node(AST_Binary, elements[0], {
operator : "+",
left : prev,
right : el
left : make_node(AST_String, self, { value: "" }),
right : elements[0]
});
}, first).optimize(compressor);
}
if (separator == "") {
var first;
if (elements[0].is_string(compressor)
|| elements[1].is_string(compressor)) {
first = elements.shift();
} else {
first = make_node(AST_String, self, { value: "" });
}
return elements.reduce(function(prev, el){
return make_node(AST_Binary, el, {
operator : "+",
left : prev,
right : el
});
}, first).optimize(compressor);
}
// need this awkward cloning to not affect original element
// best_of will decide which one to get through.
var node = self.clone();
node.expression = node.expression.clone();
node.expression.expression = node.expression.expression.clone();
node.expression.expression.elements = elements;
return best_of(compressor, self, node);
}
// need this awkward cloning to not affect original element
// best_of will decide which one to get through.
var node = self.clone();
node.expression = node.expression.clone();
node.expression.expression = node.expression.expression.clone();
node.expression.expression.elements = elements;
return best_of(compressor, self, node);
}
else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
var arg = self.args[0];
var index = arg ? arg.evaluate(compressor) : 0;
if (index !== arg) {
return make_node(AST_Sub, exp, {
expression: exp.expression,
property: make_node_from_constant(index | 0, arg || exp)
}).optimize(compressor);
break;
case "charAt":
if (exp.expression.is_string(compressor)) {
var arg = self.args[0];
var index = arg ? arg.evaluate(compressor) : 0;
if (index !== arg) {
return make_node(AST_Sub, exp, {
expression: exp.expression,
property: make_node_from_constant(index | 0, arg || exp)
}).optimize(compressor);
}
}
break;
}
}
if (compressor.option("unsafe_Func")