aboutsummaryrefslogtreecommitdiff
path: root/lib/compress.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compress.js')
-rw-r--r--lib/compress.js51
1 files changed, 29 insertions, 22 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 638fb7c0..57df130a 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -69,7 +69,7 @@ function Compressor(options, false_by_default) {
if_return : !false_by_default,
inline : !false_by_default,
join_vars : !false_by_default,
- keep_fargs : true,
+ keep_fargs : false_by_default || "strict",
keep_fnames : false,
keep_infinity : false,
loops : !false_by_default,
@@ -104,6 +104,17 @@ function Compressor(options, false_by_default) {
}
}
if (this.options["inline"] === true) this.options["inline"] = 3;
+ var keep_fargs = this.options["keep_fargs"];
+ this.drop_fargs = keep_fargs == "strict" ? function(lambda) {
+ if (lambda.length_read) return false;
+ var name = lambda.name;
+ if (!name) return true;
+ if (name.fixed_value() !== lambda) return false;
+ var def = name.definition();
+ if (def.direct_access) return false;
+ var escaped = def.escaped;
+ return escaped && escaped.depth != 1;
+ } : keep_fargs ? return_false : return_true;
var pure_funcs = this.options["pure_funcs"];
if (typeof pure_funcs == "function") {
this.pure_funcs = pure_funcs;
@@ -118,6 +129,8 @@ function Compressor(options, false_by_default) {
} else {
this.pure_funcs = return_true;
}
+ var sequences = this.options["sequences"];
+ this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
var top_retain = this.options["top_retain"];
if (top_retain instanceof RegExp) {
this.top_retain = function(def) {
@@ -141,8 +154,6 @@ function Compressor(options, false_by_default) {
funcs: toplevel,
vars: toplevel
};
- var sequences = this.options["sequences"];
- this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
}
Compressor.prototype = new TreeTransformer;
@@ -272,14 +283,19 @@ merge(Compressor.prototype, {
self.transform(tt);
});
- function read_property(obj, key) {
- key = get_value(key);
+ function read_property(obj, node) {
+ var key = node.getProperty();
if (key instanceof AST_Node) return;
var value;
if (obj instanceof AST_Array) {
var elements = obj.elements;
if (key == "length") return make_node_from_constant(elements.length, obj);
if (typeof key == "number" && key in elements) value = elements[key];
+ } else if (obj instanceof AST_Lambda) {
+ if (key == "length") {
+ obj.length_read = true;
+ return make_node_from_constant(obj.argnames.length, obj);
+ }
} else if (obj instanceof AST_Object) {
key = "" + key;
var props = obj.properties;
@@ -326,7 +342,7 @@ merge(Compressor.prototype, {
return is_modified(compressor, tw, obj, obj, level + 2);
}
if (parent instanceof AST_PropAccess && parent.expression === node) {
- var prop = read_property(value, parent.property);
+ var prop = read_property(value, parent);
return !immutable && is_modified(compressor, tw, parent, prop, level + 1);
}
}
@@ -490,13 +506,15 @@ merge(Compressor.prototype, {
var obj = tw.parent(level + 1);
mark_escaped(tw, d, scope, obj, obj, level + 2, depth);
} else if (parent instanceof AST_PropAccess && node === parent.expression) {
- value = read_property(value, parent.property);
+ value = read_property(value, parent);
mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
if (value) return;
}
if (level > 0) return;
+ if (parent instanceof AST_Call && node === parent.expression) return;
if (parent instanceof AST_Sequence && node !== parent.tail_node()) return;
if (parent instanceof AST_SimpleStatement) return;
+ if (parent instanceof AST_Unary) return;
d.direct_access = true;
}
@@ -2217,18 +2235,6 @@ merge(Compressor.prototype, {
}));
}
- function get_value(key) {
- if (key instanceof AST_Constant) {
- return key.getValue();
- }
- if (key instanceof AST_UnaryPrefix
- && key.operator == "void"
- && key.expression instanceof AST_Constant) {
- return;
- }
- return key;
- }
-
function is_undefined(node, compressor) {
return node.is_undefined
|| node instanceof AST_Undefined
@@ -3621,7 +3627,7 @@ merge(Compressor.prototype, {
node.name = null;
}
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
- var trim = !compressor.option("keep_fargs");
+ var trim = compressor.drop_fargs(node);
for (var a = node.argnames, i = a.length; --i >= 0;) {
var sym = a[i];
if (!(sym.definition().id in in_use_ids)) {
@@ -4068,7 +4074,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
var defs = defs_by_id[node.expression.definition().id];
if (defs) {
- var def = defs.get(get_value(node.property));
+ var def = defs.get(node.getProperty());
var sym = make_node(AST_SymbolRef, node, {
name: def.name,
scope: node.expression.scope,
@@ -6652,7 +6658,7 @@ merge(Compressor.prototype, {
|| def.orig.length > 1) {
argname = null;
}
- } else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) {
+ } else if (!argname && compressor.drop_fargs(fn) && index < fn.argnames.length + 5) {
while (index >= fn.argnames.length) {
argname = make_node(AST_SymbolFunarg, fn, {
name: fn.make_var_name("argument_" + fn.argnames.length),
@@ -6665,6 +6671,7 @@ merge(Compressor.prototype, {
if (argname && find_if(function(node) {
return node.name === argname.name;
}, fn.argnames) === argname) {
+ expr.definition().reassigned = false;
var sym = make_node(AST_SymbolRef, self, argname);
sym.reference({});
delete argname.__unused;