new compress swtich for inlining const variables.

This commit is contained in:
Xiaoyi Shi 2013-06-06 17:30:34 +08:00
parent a4889a0f2e
commit b9fea8e7e9
2 changed files with 130 additions and 2 deletions

View File

@ -59,6 +59,8 @@ function Compressor(options, false_by_default) {
evaluate : !false_by_default,
booleans : !false_by_default,
loops : !false_by_default,
inlineconst : false,
inlinestr : false,
unused : !false_by_default,
hoist_funs : !false_by_default,
hoist_vars : false,
@ -83,6 +85,7 @@ merge(Compressor.prototype, {
before: function(node, descend, in_list) {
if (node._squeezed) return node;
if (node instanceof AST_Scope) {
node.inline_const_primitive(this);
node.drop_unused(this);
node = node.hoist_declarations(this);
}
@ -593,8 +596,8 @@ merge(Compressor.prototype, {
// of the array is always an AST_Node descendant; when
// evaluation was successful it's a node that represents the
// constant; otherwise it's the original node.
AST_Node.DEFMETHOD("evaluate", function(compressor){
if (!compressor.option("evaluate")) return [ this ];
AST_Node.DEFMETHOD("evaluate", function(compressor, ignore_setting){
if (!compressor.option("evaluate") && !ignore_setting) return [ this ];
try {
var val = this._eval(), ast = make_node_from_constant(compressor, val, this);
return [ best_of(ast, this), val ];
@ -886,6 +889,64 @@ merge(Compressor.prototype, {
return self;
});
AST_Scope.DEFMETHOD("inline_const_primitive", function(compressor){
var self = this;
var inlineStringThreshold = compressor.option("inlinestr");
if (compressor.option("inlineconst")
&& !(self instanceof AST_Toplevel)
&& !self.uses_eval
) {
var in_use = [];
var definitions = {};
// pass 1: find out symbols defined for only once and has
// could be evaluate as number or bool constant.
var scope = this;
var tw = new TreeWalker(function(node, descend){
if (node !== self) {
if (node instanceof AST_Definitions && scope === self) {
node.definitions.forEach(function(def){
if (def.value) {
var value = def.value.evaluate(compressor, true);
def.value = value[0];
if (value.length > 1) {
if (!(typeof value[1] === 'string' && value[1].length >= inlineStringThreshold))
definitions[def.name.name] = value[1];
}
}
});
return true;
}
if (node instanceof AST_Assign) {
if (definitions.hasOwnProperty(node.left.name))
delete definitions[node.left.name];
return true;
}
if (node instanceof AST_Scope) {
var save_scope = scope;
scope = node;
descend();
scope = save_scope;
return true;
}
}
});
self.walk(tw);
// pass 2: we should replace symbols refer to constants
// with corresponding values.
var tt = new TreeTransformer(
function before(node, descend, in_list) {
if (node instanceof AST_SymbolRef) {
if (definitions.hasOwnProperty(node.name)) {
return make_node_from_constant(compressor, definitions[node.name], node.orig);
}
}
}
);
self.transform(tt);
}
});
AST_Scope.DEFMETHOD("drop_unused", function(compressor){
var self = this;
if (compressor.option("unused")

View File

@ -0,0 +1,67 @@
inlineconst_number: {
options = { inlineconst: true };
input: {
function f(c) {
var a = 5, b = 10;
return a + b + c;
}
}
expect: {
function f(c) {
var a = 5, b = 10;
return 5 + 10 + c;
}
}
}
inlineconst_bool_and_null: {
options = { inlineconst: true };
input: {
function f(c) {
var a = true, b = false, n = null;
return (n || b || a) ^ c;
}
}
expect: {
function f(c) {
var a = true, b = false, n = null;
return (null || false || true) ^ c;
}
}
}
inlineconst_string: {
options = { inlineconst: true, inlinestr: 2 };
input: {
function f() {
var s1 = "1", s2 = "12";
return s1 + s2;
}
}
expect: {
function f() {
var s1 = "1", s2 = "12";
return "1" + s2;
}
}
}
inlineconst_in_nested_function: {
options = { inlineconst: true };
input: {
function f() {
var x = 1;
return function t() {
return x + 1;
};
}
}
expect: {
function f() {
var x = 1;
return function t() {
return 1 + 1;
};
}
}
}