Compare commits

...

9 Commits

Author SHA1 Message Date
Alex Lam S.L
af4ea3ff69 v3.11.5 2020-11-03 08:59:02 +08:00
Alex Lam S.L
e7643248a3 fix corner case in merge_vars (#4258)
fixes #4257
2020-11-02 01:01:00 +08:00
Alex Lam S.L
68091dbf69 fix corner case in merge_vars (#4256)
fixes #4255
2020-11-01 14:34:07 +08:00
Alex Lam S.L
cbf7269296 fix corner case in merge_vars (#4254)
fixes #4253
2020-11-01 10:37:21 +08:00
Alex Lam S.L
d8563caba7 improve resilience against spurious time-outs (#4252) 2020-10-30 11:06:48 +08:00
Alex Lam S.L
2e0ad40fe6 fix corner case in ie8 (#4251)
fixes #4250
2020-10-30 11:06:31 +08:00
Alex Lam S.L
5d12abc41b fix corner cases in collapse_vars (#4249)
fixes #4248
2020-10-30 10:04:23 +08:00
Alex Lam S.L
79e5c3f564 improve warnings (#4247)
closes #4244
2020-10-27 17:39:33 +08:00
Alex Lam S.L
607f87c5cd fix corner case in booleans (#4246)
fixes #4245
2020-10-26 18:53:58 +08:00
17 changed files with 384 additions and 97 deletions

View File

@@ -276,7 +276,9 @@ function convert_ast(fn) {
function run() {
var content = options.sourceMap && options.sourceMap.content;
if (content && content != "inline") {
UglifyJS.AST_Node.info("Using input source map: " + content);
UglifyJS.AST_Node.info("Using input source map: {content}", {
content : content,
});
options.sourceMap.content = read_file(content, content);
}
try {

View File

@@ -137,17 +137,17 @@ var AST_Node = DEFNODE("Node", "start end", {
}, null);
(AST_Node.log_function = function(fn, verbose) {
var printed = Object.create(null);
if (fn) {
AST_Node.info = verbose ? function(text, props) {
log("INFO: " + string_template(text, props));
} : noop;
AST_Node.warn = function(text, props) {
log("WARN: " + string_template(text, props));
};
} else {
if (!fn) {
AST_Node.info = AST_Node.warn = noop;
return;
}
var printed = Object.create(null);
AST_Node.info = verbose ? function(text, props) {
log("INFO: " + string_template(text, props));
} : noop;
AST_Node.warn = function(text, props) {
log("WARN: " + string_template(text, props));
};
function log(msg) {
if (printed[msg]) return;

View File

@@ -192,7 +192,11 @@ merge(Compressor.prototype, {
node.walk(new TreeWalker(function() {
count++;
}));
AST_Node.info("pass " + pass + ": last_count: " + min_count + ", count: " + count);
AST_Node.info("pass {pass}: last_count: {min_count}, count: {count}", {
pass: pass,
min_count: min_count,
count: count,
});
if (count < min_count) {
min_count = count;
stopping = false;
@@ -1340,11 +1344,11 @@ merge(Compressor.prototype, {
replaced++;
}
CHANGED = abort = true;
AST_Node.info("Collapsing {name} [{file}:{line},{col}]", {
name: node.print_to_string(),
AST_Node.info("Collapsing {node} [{file}:{line},{col}]", {
node: node,
file: node.start.file,
line: node.start.line,
col: node.start.col
col: node.start.col,
});
if (candidate instanceof AST_UnaryPostfix) {
if (lhs instanceof AST_SymbolRef) lhs.definition().fixed = false;
@@ -1552,12 +1556,17 @@ merge(Compressor.prototype, {
if (node instanceof AST_Defun) return funarg && lhs.name === node.name.name;
if (node instanceof AST_DWLoop) return true;
if (node instanceof AST_LoopControl) return true;
if (node instanceof AST_SymbolRef) {
if (node.is_declared(compressor) ? node.fixed_value() || all(node.definition().orig, function(sym) {
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
}) : parent instanceof AST_Assign && parent.operator == "=" && parent.left === node) return false;
if (!replace_all) return true;
scan_rhs = false;
return false;
}
if (node instanceof AST_Try) return true;
if (node instanceof AST_With) return true;
if (replace_all) return false;
return node instanceof AST_SymbolRef
&& !node.is_declared(compressor)
&& !(parent instanceof AST_Assign && parent.operator == "=" && parent.left === node);
return false;
}
function in_conditional(node, parent) {
@@ -1706,6 +1715,8 @@ merge(Compressor.prototype, {
extract_candidates(expr.condition);
extract_candidates(expr.consequent);
extract_candidates(expr.alternative);
} else if (expr instanceof AST_Definitions) {
expr.definitions.forEach(extract_candidates);
} else if (expr instanceof AST_Dot) {
extract_candidates(expr.expression);
} else if (expr instanceof AST_DWLoop) {
@@ -1759,18 +1770,18 @@ merge(Compressor.prototype, {
} else {
extract_candidates(expr.expression);
}
} else if (expr instanceof AST_Var) {
expr.definitions.forEach(extract_candidates);
} else if (expr instanceof AST_VarDef) {
if (expr.value) {
var def = expr.name.definition();
if (def.references.length > def.replaced) {
candidates.push(hit_stack.slice());
if (expr.name instanceof AST_SymbolVar) {
if (expr.value) {
var def = expr.name.definition();
if (def.references.length > def.replaced) {
candidates.push(hit_stack.slice());
}
} else {
declare_only[expr.name.name] = (declare_only[expr.name.name] || 0) + 1;
}
extract_candidates(expr.value);
} else {
declare_only[expr.name.name] = (declare_only[expr.name.name] || 0) + 1;
}
if (expr.value) extract_candidates(expr.value);
}
hit_stack.pop();
}
@@ -2799,14 +2810,15 @@ merge(Compressor.prototype, {
}
function extract_declarations_from_unreachable_code(compressor, stat, target) {
if (!(stat instanceof AST_Defun)) {
if (!(stat instanceof AST_Definitions || stat instanceof AST_Defun)) {
AST_Node.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
}
var block;
stat.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_Definitions) {
AST_Node.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
node.remove_initializers(compressor);
if (node.remove_initializers(compressor)) {
AST_Node.warn("Dropping initialization in unreachable code [{file}:{line},{col}]", node.start);
}
push(node);
return true;
}
@@ -3273,7 +3285,12 @@ merge(Compressor.prototype, {
}
function warn(node) {
AST_Node.warn("global_defs " + node.print_to_string() + " redefined [{file}:{line},{col}]", node.start);
AST_Node.warn("global_defs {node} redefined [{file}:{line},{col}]", {
node: node,
file: node.start.file,
line: node.start.line,
col: node.start.col,
});
}
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
@@ -3878,10 +3895,10 @@ merge(Compressor.prototype, {
return val[key].apply(val, args);
} catch (ex) {
AST_Node.warn("Error evaluating {code} [{file}:{line},{col}]", {
code: this.print_to_string(),
code: this,
file: this.start.file,
line: this.start.line,
col: this.start.col
col: this.start.col,
});
} finally {
if (val instanceof RegExp) val.lastIndex = 0;
@@ -4452,6 +4469,11 @@ merge(Compressor.prototype, {
pop();
return true;
}
if (node instanceof AST_Break) {
var target = tw.loopcontrol_target(node);
if (!(target instanceof AST_IterationStatement)) insert(target);
return true;
}
if (node instanceof AST_Conditional) {
node.condition.walk(tw);
push();
@@ -4471,20 +4493,7 @@ merge(Compressor.prototype, {
}
if (node instanceof AST_Continue) {
var target = tw.loopcontrol_target(node);
if (!(target instanceof AST_Do)) return true;
var stack = [];
while (!HOP(segment, "block") || segment.block !== target) {
stack.push(segment);
pop();
}
segment.loop = "c";
push();
while (stack.length) {
var seg = stack.pop();
push();
if (HOP(seg, "block")) segment.block = seg.block;
if (HOP(seg, "loop")) segment.loop = seg.loop;
}
if (target instanceof AST_Do) insert(target);
return true;
}
if (node instanceof AST_Do) {
@@ -4493,7 +4502,7 @@ merge(Compressor.prototype, {
segment.loop = true;
var save = segment;
node.body.walk(tw);
if (segment.loop == "c") segment = save;
if (segment.inserted === node) segment = save;
node.condition.walk(tw);
pop();
return true;
@@ -4534,7 +4543,9 @@ merge(Compressor.prototype, {
if (node instanceof AST_LabeledStatement) {
push();
segment.block = node;
var save = segment;
node.body.walk(tw);
if (segment.inserted === node) segment = save;
pop();
return true;
}
@@ -4570,7 +4581,10 @@ merge(Compressor.prototype, {
segment = save;
node.body.forEach(function(branch) {
push();
segment.block = node;
var save = segment;
walk_body(branch, tw);
if (segment.inserted === node) segment = save;
pop();
});
return true;
@@ -4725,6 +4739,27 @@ merge(Compressor.prototype, {
});
}
function insert(target) {
var stack = [];
while (true) {
if (HOP(segment, "block")) {
var block = segment.block;
if (block instanceof AST_LabeledStatement) block = block.body;
if (block === target) break;
}
stack.push(segment);
pop();
}
segment.inserted = segment.block;
push();
while (stack.length) {
var seg = stack.pop();
push();
if (HOP(seg, "block")) segment.block = seg.block;
if (HOP(seg, "loop")) segment.loop = seg.loop;
}
}
function must_visit(base, segment) {
return base === segment || base.isPrototypeOf(segment);
}
@@ -4992,7 +5027,7 @@ merge(Compressor.prototype, {
var old_def, var_defs = var_defs_by_id.get(sym.id);
if (!def.value) {
if (var_defs.length > 1) {
AST_Node.warn("Dropping duplicated declaration of variable {name} [{file}:{line},{col}]", template(def.name));
AST_Node.info("Dropping declaration of variable {name} [{file}:{line},{col}]", template(def.name));
remove(var_defs, def);
sym.eliminated++;
} else {
@@ -5183,7 +5218,10 @@ merge(Compressor.prototype, {
var def = sym.definition();
if (!def) return;
if (def.id in in_use_ids) return;
if (def.scope !== self && self.find_variable(sym) === def) return;
if (def.scope !== self) {
var d = self.find_variable(sym);
if ((d && d.redefined() || d) === def) return;
}
log(sym, "Dropping unused loop variable {name}");
if (for_ins[def.id] === node) delete for_ins[def.id];
var body = [];
@@ -5226,7 +5264,7 @@ merge(Compressor.prototype, {
name: sym.name,
file: sym.start.file,
line: sym.start.line,
col : sym.start.col
col : sym.start.col,
};
}
@@ -6662,19 +6700,21 @@ merge(Compressor.prototype, {
this.definitions.forEach(function(def) {
def.value = make_node(AST_Undefined, def).optimize(compressor);
});
return true;
});
AST_Let.DEFMETHOD("remove_initializers", function() {
function remove_initializers() {
var CHANGED = false;
this.definitions.forEach(function(def) {
if (!def.value) return;
def.value = null;
CHANGED = true;
});
});
return CHANGED;
}
AST_Var.DEFMETHOD("remove_initializers", function() {
this.definitions.forEach(function(def) {
def.value = null;
});
});
AST_Let.DEFMETHOD("remove_initializers", remove_initializers);
AST_Var.DEFMETHOD("remove_initializers", remove_initializers);
AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
var reduce_vars = compressor.option("reduce_vars");
@@ -6827,7 +6867,7 @@ merge(Compressor.prototype, {
length: length,
file: self.start.file,
line: self.start.line,
col: self.start.col
col: self.start.col,
});
break;
}
@@ -6884,10 +6924,10 @@ merge(Compressor.prototype, {
}));
} catch (ex) {
AST_Node.warn("Error converting {expr} [{file}:{line},{col}]", {
expr: self.print_to_string(),
expr: self,
file: self.start.file,
line: self.start.line,
col: self.start.col
col: self.start.col,
});
}
}
@@ -7598,7 +7638,9 @@ merge(Compressor.prototype, {
// typeof always returns a non-empty string, thus it's
// always true in booleans
AST_Node.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
return (exp instanceof AST_SymbolRef ? make_node(AST_True, self) : make_sequence(self, [
return (exp instanceof AST_SymbolRef && all(exp.definition().orig, function(sym) {
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);
}) ? make_node(AST_True, self) : make_sequence(self, [
exp,
make_node(AST_True, self)
])).optimize(compressor);
@@ -9300,7 +9342,7 @@ merge(Compressor.prototype, {
prop: self.property,
file: self.start.file,
line: self.start.line,
col: self.start.col
col: self.start.col,
});
}
var parent = compressor.parent();

View File

@@ -33,7 +33,9 @@ function read_source_map(name, toplevel) {
return to_ascii(match[2]);
}
}
AST_Node.warn("inline source map not found: " + name);
AST_Node.warn("inline source map not found: {name}", {
name: name,
});
}
function parse_source_map(content) {
@@ -258,6 +260,7 @@ function minify(files, options) {
} catch (ex) {
return { error: ex };
} finally {
AST_Node.log_function();
AST_Node.disable_validation();
}
}

View File

@@ -143,8 +143,9 @@ function push_uniq(array, el) {
}
function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p) {
return props && props[p];
return text.replace(/\{([^}]+)\}/g, function(str, p) {
var value = props[p];
return value instanceof AST_Node ? value.print_to_string() : value;
});
}

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.11.4",
"version": "3.11.5",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -315,6 +315,7 @@ function test_case(test) {
if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);
}
var output_code = make_code(output, output_options);
U.AST_Node.log_function();
if (expect != output_code) {
log([
"!!! failed",
@@ -386,7 +387,7 @@ function test_case(test) {
mangle: test.mangle
});
var actual = stdout[toplevel ? 1 : 0];
if (test.expect_stdout === true) {
if (test.expect_stdout === true || test.expect_stdout instanceof Error && test.expect_stdout.name === actual.name) {
test.expect_stdout = actual;
}
if (!sandbox.same_stdout(test.expect_stdout, actual)) {

View File

@@ -8577,3 +8577,28 @@ issue_4242: {
}
expect_stdout: "undefined"
}
issue_4248: {
options = {
collapse_vars: true,
}
input: {
var a = 0;
try {
a = 1;
b[1];
} catch (e) {
console.log(a);
}
}
expect: {
var a = 0;
try {
a = 1;
b[1];
} catch (e) {
console.log(a);
}
}
expect_stdout: "1"
}

View File

@@ -83,13 +83,11 @@ ifs_3_should_warn: {
"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]",
"WARN: Condition always false [test/compress/conditionals.js:3,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]",
"WARN: Declarations in unreachable code! [test/compress/conditionals.js:4,12]",
"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]",
"WARN: Boolean || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]",
"WARN: Condition always true [test/compress/conditionals.js:10,12]",
"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]",
"WARN: Declarations in unreachable code! [test/compress/conditionals.js:13,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]",
"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]",
]

View File

@@ -1084,3 +1084,54 @@ issue_4231: {
}
expect_stdout: "function"
}
issue_4245: {
options = {
booleans: true,
}
input: {
const a = f();
function f() {
typeof a;
}
}
expect: {
const a = f();
function f() {
a,
1;
}
}
expect_stdout: true
}
issue_4248: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
try {
(function() {
a = "PASS";
b[a];
const b = 0;
})();
} catch (e) {
console.log(a);
}
}
expect: {
var a = "FAIL";
try {
(function() {
a = "PASS";
b[a];
const b = 0;
})();
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
}

View File

@@ -61,8 +61,6 @@ dead_code_2_should_warn: {
expect_stdout: true
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/dead-code.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:10,16]",
"WARN: Dropping unreachable code [test/compress/dead-code.js:10,16]",
]
node_version: "<=4"
}
@@ -103,11 +101,9 @@ dead_code_constant_boolean_should_warn_more: {
"WARN: + in boolean context always true [test/compress/dead-code.js:1,33]",
"WARN: Boolean || always true [test/compress/dead-code.js:1,16]",
"WARN: Dropping unreachable code [test/compress/dead-code.js:1,45]",
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:3,12]",
"WARN: Boolean expression always true [test/compress/dead-code.js:6,47]",
"WARN: Boolean && always false [test/compress/dead-code.js:6,28]",
"WARN: Dropping unreachable code [test/compress/dead-code.js:6,63]",
"WARN: Declarations in unreachable code! [test/compress/dead-code.js:9,12]",
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:1,15]",
"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:6,28]",
]

View File

@@ -2877,3 +2877,30 @@ issue_4235: {
}
expect_stdout: "undefined"
}
issue_4250: {
options = {
ie8: true,
loops: true,
unused: true,
}
input: {
console.log(function f() {
(function() {
for (f in "f");
})();
return f;
var f;
}());
}
expect: {
console.log(function f() {
(function() {
for (f in "f");
})();
return f;
var f;
}());
}
expect_stdout: "0"
}

View File

@@ -39,7 +39,7 @@ non_hoisted_function_after_return: {
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]"
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]",
]
}
@@ -84,15 +84,12 @@ non_hoisted_function_after_return_2a: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"INFO: pass 0: last_count: Infinity, count: 35",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
@@ -138,10 +135,7 @@ non_hoisted_function_after_return_2b: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
]
}
@@ -242,15 +236,12 @@ non_hoisted_function_after_return_2a_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
"INFO: pass 0: last_count: Infinity, count: 46",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
@@ -301,10 +292,7 @@ non_hoisted_function_after_return_2b_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
]
}

View File

@@ -893,3 +893,60 @@ issue_4231: {
expect_stdout: "function"
node_version: ">=4"
}
issue_4245: {
options = {
booleans: true,
}
input: {
"use strict";
let a = f();
function f() {
typeof a;
}
}
expect: {
"use strict";
let a = f();
function f() {
a,
1;
}
}
expect_stdout: ReferenceError("a is not defined")
node_version: ">=4"
}
issue_4248: {
options = {
collapse_vars: true,
}
input: {
var a = "FAIL";
try {
(function() {
"use strict";
a = "PASS";
b[a];
let b;
})();
} catch (e) {
console.log(a);
}
}
expect: {
var a = "FAIL";
try {
(function() {
"use strict";
a = "PASS";
b[a];
let b;
})();
} catch (e) {
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=4"
}

View File

@@ -3092,3 +3092,94 @@ issue_4237_2: {
}
expect_stdout: "PASS"
}
issue_4253: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
switch (0) {
default:
var a = "FAIL";
a = a && a;
try {
break;
} catch (e) {}
var b = 42;
}
console.log(b);
}
expect: {
switch (0) {
default:
var a = "FAIL";
a = a && a;
try {
break;
} catch (e) {}
var b = 42;
}
console.log(b);
}
expect_stdout: "undefined"
}
issue_4255: {
options = {
dead_code: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: for (var a = 2; --a;)
for (var b = 0; console.log(b); --b)
break L;
}
expect: {
L: for (var a = 2; --a;) {
var b = 0;
if (console.log(b))
break L;
}
}
expect_stdout: "0"
}
issue_4257: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a = 0;
for (var i = 0; i < 2; i++)
switch (--a) {
case 0:
var b = 0;
break;
case 0:
default:
var c = 1 + (0 | (b && A));
console.log(c);
}
}
expect: {
var a = 0;
for (var i = 0; i < 2; i++)
switch (--a) {
case 0:
var b = 0;
break;
case 0:
default:
var c = 1 + (0 | (b && A));
console.log(c);
}
}
expect_stdout: [
"1",
"1",
]
}

View File

@@ -593,7 +593,7 @@ function is_error(result) {
}
function is_timed_out(result) {
return is_error(result) && /timed out/.test(result);
return is_error(result) && /timed out/.test(result.message);
}
function is_statement(node) {

View File

@@ -1369,7 +1369,12 @@ for (var round = 1; round <= num_iterations; round++) {
}
}
// ignore difference in error message caused by Temporal Dead Zone
if (!ok && errored) ok = uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError";
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
// ignore spurious time-outs
if (!ok && errored && /timed out/.test(original_result.message) && !/timed out/.test(uglify_result.message)) {
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = sandbox.run_code(original_code, toplevel, 10000);
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
}
// ignore difference in error message caused by `in`
// ignore difference in depth of termination caused by infinite recursion
if (!ok) {