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;
|
||||
});
|
||||
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user