minor consolidations (#2484)
- unique symbol generation - `unsafe` on `AST_Call`
This commit is contained in:
256
lib/compress.js
256
lib/compress.js
@@ -2778,18 +2778,29 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
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){
|
AST_Scope.DEFMETHOD("hoist_properties", function(compressor){
|
||||||
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 top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
|
||||||
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;
|
|
||||||
});
|
|
||||||
self.variables.each(function(def, name) {
|
|
||||||
var_names[name] = true;
|
|
||||||
});
|
|
||||||
return self.transform(new TreeTransformer(function(node) {
|
return self.transform(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;
|
||||||
@@ -2829,17 +2840,13 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function make_sym(key) {
|
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, {
|
var new_var = make_node(sym.CTOR, sym, {
|
||||||
name: name,
|
name: self.make_var_name(sym.name + "_" + key),
|
||||||
scope: self
|
scope: self
|
||||||
});
|
});
|
||||||
var def = self.def_variable(new_var);
|
var def = self.def_variable(new_var);
|
||||||
defs.set(key, def);
|
defs.set(key, def);
|
||||||
self.enclosed.push(def);
|
self.enclosed.push(def);
|
||||||
var_names[name] = true;
|
|
||||||
return new_var;
|
return new_var;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -3408,130 +3415,133 @@ merge(Compressor.prototype, {
|
|||||||
self.args.length = last;
|
self.args.length = last;
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
if (is_undeclared_ref(exp)) {
|
if (is_undeclared_ref(exp)) switch (exp.name) {
|
||||||
switch (exp.name) {
|
case "Array":
|
||||||
case "Array":
|
if (self.args.length != 1) {
|
||||||
if (self.args.length != 1) {
|
return make_node(AST_Array, self, {
|
||||||
return make_node(AST_Array, self, {
|
elements: self.args
|
||||||
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: "" })
|
|
||||||
}).optimize(compressor);
|
}).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;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
|
case "Object":
|
||||||
return make_node(AST_Binary, self, {
|
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: "" }),
|
left: make_node(AST_String, self, { value: "" }),
|
||||||
operator: "+",
|
operator: "+",
|
||||||
right: exp.expression
|
right: exp.expression
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
break;
|
||||||
else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
|
case "join":
|
||||||
var separator;
|
if (exp.expression instanceof AST_Array) EXIT: {
|
||||||
if (self.args.length > 0) {
|
var separator;
|
||||||
separator = self.args[0].evaluate(compressor);
|
if (self.args.length > 0) {
|
||||||
if (separator === self.args[0]) break EXIT; // not a constant
|
separator = self.args[0].evaluate(compressor);
|
||||||
}
|
if (separator === self.args[0]) break EXIT; // not a constant
|
||||||
var elements = [];
|
}
|
||||||
var consts = [];
|
var elements = [];
|
||||||
exp.expression.elements.forEach(function(el) {
|
var consts = [];
|
||||||
var value = el.evaluate(compressor);
|
exp.expression.elements.forEach(function(el) {
|
||||||
if (value !== el) {
|
var value = el.evaluate(compressor);
|
||||||
consts.push(value);
|
if (value !== el) {
|
||||||
} else {
|
consts.push(value);
|
||||||
if (consts.length > 0) {
|
} else {
|
||||||
elements.push(make_node(AST_String, self, {
|
if (consts.length > 0) {
|
||||||
value: consts.join(separator)
|
elements.push(make_node(AST_String, self, {
|
||||||
}));
|
value: consts.join(separator)
|
||||||
consts.length = 0;
|
}));
|
||||||
|
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 (consts.length > 0) {
|
||||||
if (separator == "") {
|
elements.push(make_node(AST_String, self, {
|
||||||
var first;
|
value: consts.join(separator)
|
||||||
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){
|
if (elements.length == 0) return make_node(AST_String, self, { value: "" });
|
||||||
return make_node(AST_Binary, el, {
|
if (elements.length == 1) {
|
||||||
|
if (elements[0].is_string(compressor)) {
|
||||||
|
return elements[0];
|
||||||
|
}
|
||||||
|
return make_node(AST_Binary, elements[0], {
|
||||||
operator : "+",
|
operator : "+",
|
||||||
left : prev,
|
left : make_node(AST_String, self, { value: "" }),
|
||||||
right : el
|
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
|
break;
|
||||||
// best_of will decide which one to get through.
|
case "charAt":
|
||||||
var node = self.clone();
|
if (exp.expression.is_string(compressor)) {
|
||||||
node.expression = node.expression.clone();
|
var arg = self.args[0];
|
||||||
node.expression.expression = node.expression.expression.clone();
|
var index = arg ? arg.evaluate(compressor) : 0;
|
||||||
node.expression.expression.elements = elements;
|
if (index !== arg) {
|
||||||
return best_of(compressor, self, node);
|
return make_node(AST_Sub, exp, {
|
||||||
}
|
expression: exp.expression,
|
||||||
else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
|
property: make_node_from_constant(index | 0, arg || exp)
|
||||||
var arg = self.args[0];
|
}).optimize(compressor);
|
||||||
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")
|
if (compressor.option("unsafe_Func")
|
||||||
|
|||||||
Reference in New Issue
Block a user