Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d758a216b | ||
|
|
af13f8dd2c | ||
|
|
88423f2574 | ||
|
|
ee632a5519 | ||
|
|
dfe47bcc42 | ||
|
|
6d3dcaa59e | ||
|
|
1bc0df1569 | ||
|
|
a98ba994bd | ||
|
|
cd671221c5 | ||
|
|
bce3919748 | ||
|
|
61b66e83f1 | ||
|
|
a5db8cd14c | ||
|
|
2021c2fa3e | ||
|
|
484d3fd8c7 | ||
|
|
3bf8699f95 |
14
lib/ast.js
14
lib/ast.js
@@ -120,6 +120,20 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
ctor.prototype._validate.call(this);
|
ctor.prototype._validate.call(this);
|
||||||
} while (ctor = ctor.BASE);
|
} while (ctor = ctor.BASE);
|
||||||
},
|
},
|
||||||
|
validate_ast: function() {
|
||||||
|
var marker = {};
|
||||||
|
this.walk(new TreeWalker(function(node) {
|
||||||
|
if (node.validate_visited === marker) {
|
||||||
|
throw new Error(string_template("cannot reuse {type} from [{file}:{line},{col}]", {
|
||||||
|
type: "AST_" + node.TYPE,
|
||||||
|
file: node.start.file,
|
||||||
|
line: node.start.line,
|
||||||
|
col: node.start.col,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
node.validate_visited = marker;
|
||||||
|
}));
|
||||||
|
},
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
(AST_Node.log_function = function(fn, verbose) {
|
(AST_Node.log_function = function(fn, verbose) {
|
||||||
|
|||||||
@@ -587,7 +587,10 @@ merge(Compressor.prototype, {
|
|||||||
d.assignments++;
|
d.assignments++;
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
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)) {
|
||||||
|
d.fixed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
var safe = eq || safe_to_read(tw, d);
|
var safe = eq || safe_to_read(tw, d);
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
if (safe && safe_to_assign(tw, d)) {
|
if (safe && safe_to_assign(tw, d)) {
|
||||||
@@ -600,6 +603,7 @@ merge(Compressor.prototype, {
|
|||||||
return node.right;
|
return node.right;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
if (d.single_use) d.single_use = false;
|
||||||
sym.fixed = d.fixed = function() {
|
sym.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),
|
||||||
@@ -896,6 +900,7 @@ merge(Compressor.prototype, {
|
|||||||
if (safe_to_read(tw, d) && safe_to_assign(tw, d)) {
|
if (safe_to_read(tw, d) && safe_to_assign(tw, d)) {
|
||||||
push_ref(d, exp);
|
push_ref(d, exp);
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
|
if (d.single_use) d.single_use = false;
|
||||||
d.fixed = function() {
|
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),
|
||||||
@@ -1197,7 +1202,9 @@ merge(Compressor.prototype, {
|
|||||||
function find_loop_scope_try() {
|
function find_loop_scope_try() {
|
||||||
var node = compressor.self(), level = 0;
|
var node = compressor.self(), level = 0;
|
||||||
do {
|
do {
|
||||||
if (node instanceof AST_Catch || node instanceof AST_Finally) {
|
if (node instanceof AST_Catch) {
|
||||||
|
if (!compressor.parent(level).bfinally) level++;
|
||||||
|
} else if (node instanceof AST_Finally) {
|
||||||
level++;
|
level++;
|
||||||
} else if (node instanceof AST_IterationStatement) {
|
} else if (node instanceof AST_IterationStatement) {
|
||||||
in_loop = true;
|
in_loop = true;
|
||||||
@@ -3065,7 +3072,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
(function(def) {
|
(function(def) {
|
||||||
function to_node(value, orig) {
|
function to_node(value, orig) {
|
||||||
if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
|
if (value instanceof AST_Node) return value.clone(true);
|
||||||
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
||||||
elements: value.map(function(value) {
|
elements: value.map(function(value) {
|
||||||
return to_node(value, orig);
|
return to_node(value, orig);
|
||||||
@@ -4454,8 +4461,18 @@ merge(Compressor.prototype, {
|
|||||||
var sym = def.name.definition();
|
var sym = def.name.definition();
|
||||||
if (!drop_vars || sym.id in in_use_ids) {
|
if (!drop_vars || sym.id in in_use_ids) {
|
||||||
if (def.value && indexOf_assign(sym, def) < 0) {
|
if (def.value && indexOf_assign(sym, def) < 0) {
|
||||||
def.value = def.value.drop_side_effect_free(compressor);
|
var write_only = def.value.write_only;
|
||||||
if (def.value) def.value.tail_node().write_only = false;
|
var value = def.value.drop_side_effect_free(compressor);
|
||||||
|
if (def.value !== value) {
|
||||||
|
def.value = value && make_sequence(def.value, [
|
||||||
|
value,
|
||||||
|
make_node(AST_Number, def.value, {
|
||||||
|
value: 0
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
} else if (def.value.write_only !== write_only) {
|
||||||
|
def.value.write_only = write_only;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var old_def, var_defs = var_defs_by_id.get(sym.id);
|
var old_def, var_defs = var_defs_by_id.get(sym.id);
|
||||||
if (!def.value) {
|
if (!def.value) {
|
||||||
@@ -5063,6 +5080,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
self.transform(new TreeTransformer(function(node, descend) {
|
self.transform(new TreeTransformer(function(node, descend) {
|
||||||
|
if (node instanceof AST_Binary) return replace("right");
|
||||||
if (node instanceof AST_PropAccess) {
|
if (node instanceof AST_PropAccess) {
|
||||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
if (!(node.expression instanceof AST_SymbolRef)) return;
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
@@ -5078,10 +5096,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Unary) {
|
if (node instanceof AST_Unary) {
|
||||||
if (unary_side_effects[node.operator]) return;
|
if (unary_side_effects[node.operator]) return;
|
||||||
if (!(node.expression instanceof AST_SymbolRef)) return;
|
return replace("expression");
|
||||||
if (!(node.expression.definition().id in defs_by_id)) return;
|
}
|
||||||
|
|
||||||
|
function replace(prop) {
|
||||||
|
var sym = node[prop];
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
|
if (!(sym.definition().id in defs_by_id)) return;
|
||||||
var opt = node.clone();
|
var opt = node.clone();
|
||||||
opt.expression = make_node(AST_Object, node, {
|
opt[prop] = make_node(AST_Object, sym, {
|
||||||
properties: []
|
properties: []
|
||||||
});
|
});
|
||||||
return opt;
|
return opt;
|
||||||
@@ -5303,10 +5326,7 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(this, [ expression, property ]);
|
return make_sequence(this, [ expression, property ]);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
if (!this.is_declared(compressor)) return this;
|
return this.is_declared(compressor) ? null : this;
|
||||||
var def = this.definition();
|
|
||||||
if (member(this, def.references)) def.replaced++;
|
|
||||||
return null;
|
|
||||||
});
|
});
|
||||||
def(AST_This, return_null);
|
def(AST_This, return_null);
|
||||||
def(AST_Unary, function(compressor, first_in_statement) {
|
def(AST_Unary, function(compressor, first_in_statement) {
|
||||||
@@ -5314,10 +5334,7 @@ merge(Compressor.prototype, {
|
|||||||
this.write_only = !this.expression.has_side_effects(compressor);
|
this.write_only = !this.expression.has_side_effects(compressor);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) {
|
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
|
||||||
this.expression.definition().replaced++;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (first_in_statement && expression && is_iife_call(expression)) {
|
if (first_in_statement && expression && is_iife_call(expression)) {
|
||||||
if (expression === this.expression && this.operator == "!") return this;
|
if (expression === this.expression && this.operator == "!") return this;
|
||||||
@@ -6415,16 +6432,11 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function return_value(stat) {
|
function return_value(stat) {
|
||||||
if (!stat) return make_node(AST_Undefined, self);
|
if (!stat) return make_node(AST_Undefined, self);
|
||||||
if (stat instanceof AST_Return) {
|
if (stat instanceof AST_Return) return stat.value || make_node(AST_Undefined, self);
|
||||||
if (!stat.value) return make_node(AST_Undefined, self);
|
if (stat instanceof AST_SimpleStatement) return make_node(AST_UnaryPrefix, stat, {
|
||||||
return stat.value.clone(true);
|
operator: "void",
|
||||||
}
|
expression: stat.body
|
||||||
if (stat instanceof AST_SimpleStatement) {
|
});
|
||||||
return make_node(AST_UnaryPrefix, stat, {
|
|
||||||
operator: "void",
|
|
||||||
expression: stat.body
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function can_flatten_body(stat) {
|
function can_flatten_body(stat) {
|
||||||
@@ -7630,6 +7642,8 @@ merge(Compressor.prototype, {
|
|||||||
single_use = false;
|
single_use = false;
|
||||||
} else if (recursive_ref(compressor, def)) {
|
} else if (recursive_ref(compressor, def)) {
|
||||||
single_use = false;
|
single_use = false;
|
||||||
|
} else if (compressor.option("ie8") && fixed.name && def !== fixed.name.definition()) {
|
||||||
|
single_use = false;
|
||||||
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
||||||
single_use = fixed.is_constant_expression(self.scope);
|
single_use = fixed.is_constant_expression(self.scope);
|
||||||
if (single_use == "f") {
|
if (single_use == "f") {
|
||||||
@@ -7638,8 +7652,6 @@ merge(Compressor.prototype, {
|
|||||||
scope.inlined = true;
|
scope.inlined = true;
|
||||||
} while (scope = scope.parent_scope);
|
} while (scope = scope.parent_scope);
|
||||||
}
|
}
|
||||||
} else if (compressor.option("ie8") && fixed.name && def !== fixed.name.definition()) {
|
|
||||||
single_use = false;
|
|
||||||
}
|
}
|
||||||
if (single_use) fixed.parent_scope = self.scope;
|
if (single_use) fixed.parent_scope = self.scope;
|
||||||
} else if (!fixed || !fixed.is_constant_expression()) {
|
} else if (!fixed || !fixed.is_constant_expression()) {
|
||||||
|
|||||||
@@ -178,13 +178,17 @@ function minify(files, options) {
|
|||||||
toplevel = toplevel[action](option);
|
toplevel = toplevel[action](option);
|
||||||
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
|
||||||
});
|
});
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.mangle);
|
||||||
}
|
}
|
||||||
if (timings) timings.compress = Date.now();
|
if (timings) timings.compress = Date.now();
|
||||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
if (options.compress) {
|
||||||
|
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||||
|
if (options.validate) toplevel.validate_ast();
|
||||||
|
}
|
||||||
if (timings) timings.scope = Date.now();
|
if (timings) timings.scope = Date.now();
|
||||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||||
if (timings) timings.mangle = Date.now();
|
if (timings) timings.mangle = Date.now();
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
|
|||||||
} else {
|
} else {
|
||||||
new_def = scope.def_variable(node);
|
new_def = scope.def_variable(node);
|
||||||
}
|
}
|
||||||
|
old_def.defun = new_def.scope;
|
||||||
old_def.orig.concat(old_def.references).forEach(function(node) {
|
old_def.orig.concat(old_def.references).forEach(function(node) {
|
||||||
node.thedef = new_def;
|
node.thedef = new_def;
|
||||||
node.reference(options);
|
node.reference(options);
|
||||||
|
|||||||
@@ -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.10.0",
|
"version": "3.10.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ function test_case(test) {
|
|||||||
quote_style: 3,
|
quote_style: 3,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
input.validate_ast();
|
||||||
U.parse(input_code);
|
U.parse(input_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
@@ -315,8 +316,8 @@ function test_case(test) {
|
|||||||
output = U.mangle_properties(output, test.mangle.properties);
|
output = U.mangle_properties(output, test.mangle.properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output = make_code(output, output_options);
|
var output_code = make_code(output, output_options);
|
||||||
if (expect != output) {
|
if (expect != output_code) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
"---INPUT---",
|
"---INPUT---",
|
||||||
@@ -329,14 +330,15 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
expected: expect
|
expected: expect
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// expect == output
|
// expect == output
|
||||||
try {
|
try {
|
||||||
U.parse(output);
|
output.validate_ast();
|
||||||
|
U.parse(output_code);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
log([
|
log([
|
||||||
"!!! Test matched expected result but cannot parse output",
|
"!!! Test matched expected result but cannot parse output",
|
||||||
@@ -350,7 +352,7 @@ function test_case(test) {
|
|||||||
"",
|
"",
|
||||||
].join("\n"), {
|
].join("\n"), {
|
||||||
input: input_formatted,
|
input: input_formatted,
|
||||||
output: output,
|
output: output_code,
|
||||||
error: ex,
|
error: ex,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -409,7 +411,7 @@ function test_case(test) {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
actual = run_code(output, toplevel);
|
actual = run_code(output_code, toplevel);
|
||||||
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
if (!sandbox.same_stdout(test.expect_stdout, actual)) {
|
||||||
log([
|
log([
|
||||||
"!!! failed",
|
"!!! failed",
|
||||||
|
|||||||
@@ -8280,3 +8280,40 @@ issue_3976: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4012: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (b) {
|
||||||
|
a = "PASS";
|
||||||
|
if (--b)
|
||||||
|
return;
|
||||||
|
if (3);
|
||||||
|
} finally {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (b) {
|
||||||
|
a = "PASS";
|
||||||
|
if (--b)
|
||||||
|
return;
|
||||||
|
if (3);
|
||||||
|
} finally {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1729,7 +1729,7 @@ chained_3: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(function(a, b) {
|
console.log(function(a, b) {
|
||||||
var c = 2;
|
var c = b;
|
||||||
b++;
|
b++;
|
||||||
return c;
|
return c;
|
||||||
}(0, 2));
|
}(0, 2));
|
||||||
@@ -2718,7 +2718,7 @@ issue_3962_1: {
|
|||||||
0..toString();
|
0..toString();
|
||||||
} while (0);
|
} while (0);
|
||||||
if (c) console.log("PASS");
|
if (c) console.log("PASS");
|
||||||
})((a--, 1));
|
}((a--, 1)), 0);
|
||||||
void 0;
|
void 0;
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
@@ -2751,7 +2751,7 @@ issue_3962_2: {
|
|||||||
0..toString();
|
0..toString();
|
||||||
} while (0);
|
} while (0);
|
||||||
if (c) console.log("PASS");
|
if (c) console.log("PASS");
|
||||||
})((a--, 1));
|
}((a--, 1)), 0);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
@@ -2789,3 +2789,62 @@ issue_3986: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0"
|
expect_stdout: "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4017: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function f() {
|
||||||
|
var b = c &= 0;
|
||||||
|
var c = a++ + (A = a);
|
||||||
|
var d = c && c[f];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
console.log(function() {
|
||||||
|
c &= 0;
|
||||||
|
var c = (a++, A = a, 0);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4025: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 0, c = 0, d = a++;
|
||||||
|
try {
|
||||||
|
var e = console.log(c), f = b;
|
||||||
|
} finally {
|
||||||
|
var d = b = 1, d = c + 1;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
console.log(a, b, d);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var d, c = 0;
|
||||||
|
try {
|
||||||
|
console.log(c);
|
||||||
|
} finally {
|
||||||
|
d = c + 1;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
console.log(1, 1, d);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1 1 1",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -4747,3 +4747,34 @@ issue_3929: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4006: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
keep_fargs: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(function() {
|
||||||
|
(function(b, c) {
|
||||||
|
for (var k in console.log(c), 0)
|
||||||
|
return b += 0;
|
||||||
|
})(0, --a);
|
||||||
|
return a ? 0 : --a;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
(function(c) {
|
||||||
|
for (var k in console.log(c), 0)
|
||||||
|
return;
|
||||||
|
})(--a), a || --a;
|
||||||
|
}
|
||||||
|
expect_stdout: "-1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,20 @@ must_replace: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repeated_nodes: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
"@N": "rand()",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(N, N);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(rand(), rand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyword: {
|
keyword: {
|
||||||
options = {
|
options = {
|
||||||
global_defs: {
|
global_defs: {
|
||||||
|
|||||||
@@ -1016,3 +1016,28 @@ issue_3945_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4023: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
hoist_props: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
typeofs: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = function() {
|
||||||
|
return { p: 0 };
|
||||||
|
}();
|
||||||
|
return console.log("undefined" != typeof a);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(void 0 !== {});
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2544,12 +2544,12 @@ issue_3999: {
|
|||||||
expect: {
|
expect: {
|
||||||
(function() {
|
(function() {
|
||||||
(function f() {
|
(function f() {
|
||||||
for (var c = 0; c < 2; c++)
|
for (var o = 0; o < 2; o++)
|
||||||
try {
|
try {
|
||||||
f[0];
|
f[0];
|
||||||
} catch (f) {
|
} catch (f) {
|
||||||
var f = 0;
|
var f = 0;
|
||||||
console.log(c);
|
console.log(o);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
})(typeof f);
|
})(typeof f);
|
||||||
@@ -2593,3 +2593,124 @@ issue_4001: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4015: {
|
||||||
|
rename = true
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var n, a = 0, b;
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (b) {
|
||||||
|
(function g() {
|
||||||
|
(function b() {
|
||||||
|
a++;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var n, o = 0, c;
|
||||||
|
function t() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (c) {
|
||||||
|
(function n() {
|
||||||
|
(function c() {
|
||||||
|
o++;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t();
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4019: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (b) {}
|
||||||
|
}, a = (console.log(a.length), ++a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = function() {
|
||||||
|
try {
|
||||||
|
console.log("FAIL");
|
||||||
|
} catch (o) {}
|
||||||
|
}, o = (console.log(o.length), ++o);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4028: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a() {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
var b = a += a;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a() {
|
||||||
|
try {
|
||||||
|
A;
|
||||||
|
} catch (a) {}
|
||||||
|
}
|
||||||
|
var b = a += a;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
expect_stdout: "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2737: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
a();
|
||||||
|
})(function f() {
|
||||||
|
console.log(typeof f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
a();
|
||||||
|
})(function f() {
|
||||||
|
console.log(typeof f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|||||||
@@ -7383,3 +7383,26 @@ issue_3974: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4030: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
{
|
||||||
|
delete (a = "PASS");
|
||||||
|
A = "PASS";
|
||||||
|
}
|
||||||
|
console.log(A);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
A = "PASS";
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ operator_in: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_3983: {
|
issue_3983_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -323,7 +323,71 @@ issue_3983: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a = "PASS";
|
var a = "PASS";
|
||||||
|
g();
|
||||||
|
function g() {}
|
||||||
console.log(a);
|
console.log(a);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3983_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f() {
|
||||||
|
g && g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
function g() {
|
||||||
|
0 ? a : 0;
|
||||||
|
}
|
||||||
|
var b = a;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4008: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f(b, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f && f(a && a[a]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
function f(b, b) {
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
f(a[a]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
|||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
|
BINARY_OPS = BINARY_OPS.concat(BINARY_OPS);
|
||||||
BINARY_OPS.push(" in ");
|
BINARY_OPS.push(" in ");
|
||||||
|
|
||||||
var ASSIGNMENTS = [
|
var ASSIGNMENTS = [
|
||||||
@@ -1136,18 +1137,6 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
errorln("uglified result:");
|
errorln("uglified result:");
|
||||||
errorln(uglify_result);
|
errorln(uglify_result);
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
var reduced = reduce_test(original_code, JSON.parse(options), {
|
|
||||||
verbose: false,
|
|
||||||
}).code;
|
|
||||||
if (reduced) {
|
|
||||||
errorln();
|
|
||||||
errorln("// reduced test case (output will differ)");
|
|
||||||
errorln();
|
|
||||||
errorln(reduced);
|
|
||||||
errorln();
|
|
||||||
errorln("//-------------------------------------------------------------");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
errorln("// !!! uglify failed !!!");
|
errorln("// !!! uglify failed !!!");
|
||||||
errorln(uglify_code);
|
errorln(uglify_code);
|
||||||
@@ -1158,6 +1147,20 @@ function log(options) {
|
|||||||
errorln(original_result);
|
errorln(original_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
var reduce_options = JSON.parse(options);
|
||||||
|
reduce_options.validate = true;
|
||||||
|
var reduced = reduce_test(original_code, reduce_options, {
|
||||||
|
verbose: false,
|
||||||
|
}).code;
|
||||||
|
if (reduced) {
|
||||||
|
errorln();
|
||||||
|
errorln("// reduced test case (output will differ)");
|
||||||
|
errorln();
|
||||||
|
errorln(reduced);
|
||||||
|
errorln();
|
||||||
|
errorln("//-------------------------------------------------------------");
|
||||||
|
}
|
||||||
errorln("minify(options):");
|
errorln("minify(options):");
|
||||||
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
errorln(JSON.stringify(JSON.parse(options), null, 2));
|
||||||
errorln();
|
errorln();
|
||||||
@@ -1231,7 +1234,7 @@ function patch_try_catch(orig, toplevel) {
|
|||||||
if (typeof result != "object" || typeof result.name != "string" || typeof result.message != "string") {
|
if (typeof result != "object" || typeof result.name != "string" || typeof result.message != "string") {
|
||||||
if (!stack.filled && match[1]) stack.push({
|
if (!stack.filled && match[1]) stack.push({
|
||||||
code: code,
|
code: code,
|
||||||
index: index,
|
index: index && index - 1,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
tries: JSON.parse(JSON.stringify(tries)),
|
tries: JSON.parse(JSON.stringify(tries)),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user