Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ccdf3337b | ||
|
|
dafed54764 | ||
|
|
a84beafd1b | ||
|
|
f01cc1e413 |
@@ -773,7 +773,7 @@ var AST_Label = DEFNODE("Label", "references", {
|
|||||||
}
|
}
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
var AST_SymbolRef = DEFNODE("SymbolRef", null, {
|
var AST_SymbolRef = DEFNODE("SymbolRef", "fixed", {
|
||||||
$documentation: "Reference to some symbol (not definition/declaration)",
|
$documentation: "Reference to some symbol (not definition/declaration)",
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
|
|||||||
@@ -551,6 +551,7 @@ merge(Compressor.prototype, {
|
|||||||
mark_assignment_to_arguments(sym);
|
mark_assignment_to_arguments(sym);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (sym.fixed) delete sym.fixed;
|
||||||
var d = sym.definition();
|
var d = sym.definition();
|
||||||
var safe = safe_to_assign(tw, d, sym.scope, node.right);
|
var safe = safe_to_assign(tw, d, sym.scope, node.right);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
@@ -560,7 +561,7 @@ merge(Compressor.prototype, {
|
|||||||
var value = eq ? node.right : node;
|
var value = eq ? node.right : node;
|
||||||
if (is_modified(compressor, tw, node, value, 0)) return;
|
if (is_modified(compressor, tw, node, value, 0)) return;
|
||||||
if (!eq) d.chained = true;
|
if (!eq) d.chained = true;
|
||||||
d.fixed = eq ? function() {
|
sym.fixed = d.fixed = eq ? function() {
|
||||||
return node.right;
|
return node.right;
|
||||||
} : function() {
|
} : function() {
|
||||||
return make_node(AST_Binary, node, {
|
return make_node(AST_Binary, node, {
|
||||||
@@ -574,7 +575,7 @@ merge(Compressor.prototype, {
|
|||||||
mark(tw, d, false);
|
mark(tw, d, false);
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
mark(tw, d, true);
|
mark(tw, d, true);
|
||||||
mark_escaped(tw, d, sym.scope, node, value, 0, 1);
|
if (eq) mark_escaped(tw, d, sym.scope, node, value, 0, 1);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
@@ -730,6 +731,7 @@ merge(Compressor.prototype, {
|
|||||||
this.definition().fixed = false;
|
this.definition().fixed = false;
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(tw, descend, compressor) {
|
def(AST_SymbolRef, function(tw, descend, compressor) {
|
||||||
|
if (this.fixed) delete this.fixed;
|
||||||
var d = this.definition();
|
var d = this.definition();
|
||||||
d.references.push(this);
|
d.references.push(this);
|
||||||
if (d.references.length == 1
|
if (d.references.length == 1
|
||||||
@@ -742,7 +744,7 @@ merge(Compressor.prototype, {
|
|||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
} else if (d.fixed) {
|
} else if (d.fixed) {
|
||||||
value = this.fixed_value();
|
value = this.fixed_value();
|
||||||
if (value instanceof AST_Lambda && recursive_ref(tw, d)) {
|
if (recursive_ref(tw, d)) {
|
||||||
d.recursive_refs++;
|
d.recursive_refs++;
|
||||||
} else if (value && ref_once(tw, compressor, d)) {
|
} else if (value && ref_once(tw, compressor, d)) {
|
||||||
d.single_use = value instanceof AST_Lambda && !value.pinned()
|
d.single_use = value instanceof AST_Lambda && !value.pinned()
|
||||||
@@ -797,13 +799,14 @@ merge(Compressor.prototype, {
|
|||||||
mark_assignment_to_arguments(exp);
|
mark_assignment_to_arguments(exp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (exp.fixed) delete exp.fixed;
|
||||||
var d = exp.definition();
|
var d = exp.definition();
|
||||||
var safe = safe_to_assign(tw, d, exp.scope, true);
|
var safe = safe_to_assign(tw, d, exp.scope, true);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed) return;
|
if (!fixed) return;
|
||||||
d.chained = true;
|
d.chained = true;
|
||||||
d.fixed = function() {
|
exp.fixed = d.fixed = function() {
|
||||||
return make_node(AST_Binary, node, {
|
return make_node(AST_Binary, node, {
|
||||||
operator: node.operator.slice(0, -1),
|
operator: node.operator.slice(0, -1),
|
||||||
left: make_node(AST_UnaryPrefix, node, {
|
left: make_node(AST_UnaryPrefix, node, {
|
||||||
@@ -874,10 +877,11 @@ merge(Compressor.prototype, {
|
|||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("fixed_value", function() {
|
AST_Symbol.DEFMETHOD("fixed_value", function(final) {
|
||||||
var fixed = this.definition().fixed;
|
var fixed = this.definition().fixed;
|
||||||
if (!fixed || fixed instanceof AST_Node) return fixed;
|
if (!fixed) return fixed;
|
||||||
return fixed();
|
if (!final && this.fixed) fixed = this.fixed;
|
||||||
|
return fixed instanceof AST_Node ? fixed : fixed();
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
AST_SymbolRef.DEFMETHOD("is_immutable", function() {
|
||||||
@@ -1287,7 +1291,9 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Try) return true;
|
if (node instanceof AST_Try) return true;
|
||||||
if (node instanceof AST_With) return true;
|
if (node instanceof AST_With) return true;
|
||||||
if (replace_all) return false;
|
if (replace_all) return false;
|
||||||
return node instanceof AST_SymbolRef && !node.is_declared(compressor);
|
return node instanceof AST_SymbolRef
|
||||||
|
&& !node.is_declared(compressor)
|
||||||
|
&& !(parent instanceof AST_Assign && parent.left === node);
|
||||||
}
|
}
|
||||||
|
|
||||||
function in_conditional(node, parent) {
|
function in_conditional(node, parent) {
|
||||||
@@ -2597,9 +2603,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function convert_to_predicate(obj) {
|
function convert_to_predicate(obj) {
|
||||||
for (var key in obj) {
|
Object.keys(obj).forEach(function(key) {
|
||||||
obj[key] = makePredicate(obj[key]);
|
obj[key] = makePredicate(obj[key]);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var object_fns = [
|
var object_fns = [
|
||||||
@@ -3512,7 +3518,7 @@ merge(Compressor.prototype, {
|
|||||||
if (def.value.has_side_effects(compressor)) {
|
if (def.value.has_side_effects(compressor)) {
|
||||||
def.value.walk(tw);
|
def.value.walk(tw);
|
||||||
}
|
}
|
||||||
if (!node_def.chained && def.name.fixed_value() === def.value) {
|
if (!node_def.chained && def.name.fixed_value(true) === def.value) {
|
||||||
fixed_ids[node_def.id] = def;
|
fixed_ids[node_def.id] = def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3783,7 +3789,7 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
if (node.left === sym) {
|
if (node.left === sym) {
|
||||||
if (!node_def.chained && sym.fixed_value() === node.right) {
|
if (!node_def.chained && sym.fixed_value(true) === node.right) {
|
||||||
fixed_ids[node_def.id] = node;
|
fixed_ids[node_def.id] = node;
|
||||||
}
|
}
|
||||||
if (!node.write_only) {
|
if (!node.write_only) {
|
||||||
@@ -5102,7 +5108,7 @@ merge(Compressor.prototype, {
|
|||||||
})) {
|
})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (line instanceof AST_EmptyStatement) {
|
} else if (line instanceof AST_Defun || line instanceof AST_EmptyStatement) {
|
||||||
continue;
|
continue;
|
||||||
} else if (stat) {
|
} else if (stat) {
|
||||||
return false;
|
return false;
|
||||||
@@ -5113,16 +5119,15 @@ merge(Compressor.prototype, {
|
|||||||
return return_value(stat);
|
return return_value(stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function var_exists(catches, name) {
|
||||||
|
return catches[name] || identifier_atom[name] || scope.var_names()[name];
|
||||||
|
}
|
||||||
|
|
||||||
function can_inject_args(catches, safe_to_inject) {
|
function can_inject_args(catches, safe_to_inject) {
|
||||||
for (var i = 0; i < fn.argnames.length; i++) {
|
for (var i = 0; i < fn.argnames.length; i++) {
|
||||||
var arg = fn.argnames[i];
|
var arg = fn.argnames[i];
|
||||||
if (arg.__unused) continue;
|
if (arg.__unused) continue;
|
||||||
if (!safe_to_inject
|
if (!safe_to_inject || var_exists(catches, arg.name)) return false;
|
||||||
|| catches[arg.name]
|
|
||||||
|| identifier_atom[arg.name]
|
|
||||||
|| scope.var_names()[arg.name]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in_loop) in_loop.push(arg.definition());
|
if (in_loop) in_loop.push(arg.definition());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -5131,15 +5136,15 @@ merge(Compressor.prototype, {
|
|||||||
function can_inject_vars(catches, safe_to_inject) {
|
function can_inject_vars(catches, safe_to_inject) {
|
||||||
for (var i = 0; i < fn.body.length; i++) {
|
for (var i = 0; i < fn.body.length; i++) {
|
||||||
var stat = fn.body[i];
|
var stat = fn.body[i];
|
||||||
|
if (stat instanceof AST_Defun) {
|
||||||
|
if (!safe_to_inject || var_exists(catches, stat.name.name)) return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!(stat instanceof AST_Var)) continue;
|
if (!(stat instanceof AST_Var)) continue;
|
||||||
if (!safe_to_inject) return false;
|
if (!safe_to_inject) return false;
|
||||||
for (var j = stat.definitions.length; --j >= 0;) {
|
for (var j = stat.definitions.length; --j >= 0;) {
|
||||||
var name = stat.definitions[j].name;
|
var name = stat.definitions[j].name;
|
||||||
if (catches[name.name]
|
if (var_exists(catches, name.name)) return false;
|
||||||
|| identifier_atom[name.name]
|
|
||||||
|| scope.var_names()[name.name]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in_loop) in_loop.push(name.definition());
|
if (in_loop) in_loop.push(name.definition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5243,12 +5248,21 @@ merge(Compressor.prototype, {
|
|||||||
flatten_args(decls, expressions);
|
flatten_args(decls, expressions);
|
||||||
flatten_vars(decls, expressions);
|
flatten_vars(decls, expressions);
|
||||||
expressions.push(value);
|
expressions.push(value);
|
||||||
if (decls.length) {
|
var args = fn.body.filter(function(stat) {
|
||||||
i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
|
if (stat instanceof AST_Defun) {
|
||||||
scope.body.splice(i, 0, make_node(AST_Var, fn, {
|
var def = stat.name.definition();
|
||||||
definitions: decls
|
scope.functions.set(def.name, def);
|
||||||
}));
|
scope.variables.set(def.name, def);
|
||||||
}
|
scope.enclosed.push(def);
|
||||||
|
scope.var_names()[def.name] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
args.unshift(scope.body.indexOf(compressor.parent(level - 1)) + 1, 0);
|
||||||
|
if (decls.length) args.push(make_node(AST_Var, fn, {
|
||||||
|
definitions: decls
|
||||||
|
}));
|
||||||
|
[].splice.apply(scope.body, args);
|
||||||
return expressions;
|
return expressions;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.5.6",
|
"version": "3.5.7",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -289,3 +289,25 @@ increment_decrement_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3375: {
|
||||||
|
options = {
|
||||||
|
assignments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function(b) {
|
||||||
|
var a = b += 1;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function(b) {
|
||||||
|
var a = b += 1;
|
||||||
|
--b;
|
||||||
|
return a;
|
||||||
|
}("object"));
|
||||||
|
}
|
||||||
|
expect_stdout: "string"
|
||||||
|
}
|
||||||
|
|||||||
@@ -6157,3 +6157,24 @@ sub_property: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assign_undeclared: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = (console.log(42), function() {});
|
||||||
|
B = new A();
|
||||||
|
console.log(typeof B);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
B = new (console.log(42), function() {})();
|
||||||
|
console.log(typeof B);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42",
|
||||||
|
"object",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -2005,3 +2005,24 @@ issue_3233: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3375: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 1;
|
||||||
|
var a = c = [], c = --b + ("function" == typeof f && f());
|
||||||
|
var a = c && c[a];
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 1;
|
||||||
|
var a = [], c = --b + ("function" == typeof f && f());
|
||||||
|
a = c && c[a];
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -3003,12 +3003,10 @@ issue_3366: {
|
|||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(function() {
|
void function() {
|
||||||
function a() {}
|
this && a && console.log("PASS");
|
||||||
(function() {
|
}();
|
||||||
this && a && console.log("PASS");
|
function a() {}
|
||||||
})();
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -3041,3 +3039,29 @@ issue_3371: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class_iife: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var A = function() {
|
||||||
|
function B() {}
|
||||||
|
B.prototype.m = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
};
|
||||||
|
return B;
|
||||||
|
}();
|
||||||
|
new A().m();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var A = (B.prototype.m = function() {
|
||||||
|
console.log("PASS");
|
||||||
|
}, B);
|
||||||
|
function B() {}
|
||||||
|
new A().m();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -6737,3 +6737,21 @@ drop_side_effect_free: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "123"
|
expect_stdout: "123"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3377: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f[0], (f = 42);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f[0], (f = 42);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user