@@ -282,9 +282,6 @@ var AST_BlockScope = DEFNODE("BlockScope", "cname enclosed functions make_def pa
|
||||
|
||||
var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
||||
$documentation: "A block statement",
|
||||
initialize: function() {
|
||||
this.variables = new Dictionary();
|
||||
},
|
||||
}, AST_BlockScope);
|
||||
|
||||
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||
|
||||
@@ -1018,6 +1018,13 @@ merge(Compressor.prototype, {
|
||||
return sym instanceof AST_SymbolLambda && def.scope.name === sym;
|
||||
});
|
||||
|
||||
function find_scope(compressor) {
|
||||
var level = 0, node;
|
||||
while (node = compressor.parent(level++)) {
|
||||
if (node.variables) return node;
|
||||
}
|
||||
}
|
||||
|
||||
function is_lhs_read_only(lhs, compressor) {
|
||||
if (lhs instanceof AST_This) return true;
|
||||
if (lhs instanceof AST_SymbolRef) {
|
||||
@@ -6885,7 +6892,7 @@ merge(Compressor.prototype, {
|
||||
&& !fn.pinned()
|
||||
&& !(fn.name && fn instanceof AST_Function)
|
||||
&& (exp === fn || !recursive_ref(compressor, def = exp.definition())
|
||||
&& fn.is_constant_expression(compressor.find_parent(AST_BlockScope)))
|
||||
&& fn.is_constant_expression(find_scope(compressor)))
|
||||
&& (value = can_flatten_body(stat))
|
||||
&& !fn.contains_this()) {
|
||||
var replacing = exp === fn || compressor.option("unused") && def.references.length - def.replaced == 1;
|
||||
@@ -8303,9 +8310,16 @@ merge(Compressor.prototype, {
|
||||
return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
|
||||
}
|
||||
|
||||
function find_variable(compressor, name) {
|
||||
var level = 0, node;
|
||||
while (node = compressor.parent(level++)) {
|
||||
if (node.variables) return node.find_variable(name);
|
||||
}
|
||||
}
|
||||
|
||||
OPT(AST_Undefined, function(self, compressor) {
|
||||
if (compressor.option("unsafe_undefined")) {
|
||||
var undef = compressor.find_parent(AST_BlockScope).find_variable("undefined");
|
||||
var undef = find_scope(compressor).find_variable("undefined");
|
||||
if (undef) {
|
||||
var ref = make_node(AST_SymbolRef, self, {
|
||||
name : "undefined",
|
||||
@@ -8331,7 +8345,7 @@ merge(Compressor.prototype, {
|
||||
if (lhs && is_atomic(lhs, self)) return self;
|
||||
if (compressor.option("keep_infinity")
|
||||
&& !(lhs && !is_atomic(lhs, self))
|
||||
&& !compressor.find_parent(AST_BlockScope).find_variable("Infinity"))
|
||||
&& !find_scope(compressor).find_variable("Infinity"))
|
||||
return self;
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "/",
|
||||
@@ -8346,8 +8360,7 @@ merge(Compressor.prototype, {
|
||||
|
||||
OPT(AST_NaN, function(self, compressor) {
|
||||
var lhs = is_lhs(compressor.self(), compressor.parent());
|
||||
if (lhs && !is_atomic(lhs, self)
|
||||
|| compressor.find_parent(AST_BlockScope).find_variable("NaN")) {
|
||||
if (lhs && !is_atomic(lhs, self) || find_scope(compressor).find_variable("NaN")) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "/",
|
||||
left: make_node(AST_Number, self, {
|
||||
|
||||
@@ -5025,3 +5025,54 @@ catch_no_argname: {
|
||||
]
|
||||
node_version: ">=10"
|
||||
}
|
||||
|
||||
issue_4186: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
return function() {
|
||||
function f() {
|
||||
if (1)
|
||||
g();
|
||||
else
|
||||
(function() {
|
||||
return f;
|
||||
});
|
||||
}
|
||||
return f;
|
||||
function g() {
|
||||
if (1) {
|
||||
if (0)
|
||||
h;
|
||||
else
|
||||
h();
|
||||
var key = 0;
|
||||
}
|
||||
}
|
||||
function h() {
|
||||
return factory;
|
||||
}
|
||||
};
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function() {
|
||||
return function f() {
|
||||
1 ? void (1 && (0 ? h : h(), 0)) : function() {
|
||||
return f;
|
||||
};
|
||||
};
|
||||
function h() {
|
||||
return factory;
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
@@ -2819,3 +2819,43 @@ direct_inline_catch_redefined: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_4186: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
(function NaN() {
|
||||
var a = 1;
|
||||
while (a--)
|
||||
try {} finally {
|
||||
console.log(0/0);
|
||||
var b;
|
||||
}
|
||||
})(f);
|
||||
}
|
||||
f();
|
||||
NaN;
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function NaN() {
|
||||
var n = 1;
|
||||
while (n--)
|
||||
console.log(0/0);
|
||||
})();
|
||||
})();
|
||||
NaN;
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
@@ -499,7 +499,26 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
||||
log("// reduce test pass " + pass + ": " + testcase.length + " bytes");
|
||||
}
|
||||
}
|
||||
testcase = try_beautify(testcase, minify_options, differs.unminified_result, result_cache, max_timeout);
|
||||
var beautified = U.minify(testcase, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
braces: true,
|
||||
comments: true,
|
||||
},
|
||||
});
|
||||
testcase = {
|
||||
code: testcase,
|
||||
};
|
||||
if (!beautified.error) {
|
||||
diff = test_for_diff(beautified.code, minify_options, result_cache, max_timeout);
|
||||
if (diff && !diff.timed_out && !diff.error) {
|
||||
testcase = beautified;
|
||||
testcase.code = "// (beautified)\n" + testcase.code;
|
||||
differs = diff;
|
||||
}
|
||||
}
|
||||
var lines = [ "" ];
|
||||
if (isNaN(max_timeout)) {
|
||||
lines.push("// minify error: " + to_comment(strip_color_codes(differs.minified_result.stack)));
|
||||
@@ -538,34 +557,6 @@ function trim_trailing_whitespace(value) {
|
||||
return ("" + value).replace(/\s+$/, "");
|
||||
}
|
||||
|
||||
function try_beautify(testcase, minify_options, expected, result_cache, timeout) {
|
||||
var result = U.minify(testcase, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
beautify: true,
|
||||
braces: true,
|
||||
comments: true,
|
||||
},
|
||||
});
|
||||
if (result.error) return {
|
||||
code: testcase,
|
||||
};
|
||||
var toplevel = sandbox.has_toplevel(minify_options);
|
||||
if (isNaN(timeout)) {
|
||||
if (!U.minify(result.code, minify_options).error) return {
|
||||
code: testcase,
|
||||
};
|
||||
} else {
|
||||
var actual = run_code(result.code, toplevel, result_cache, timeout).result;
|
||||
if (!sandbox.same_stdout(expected, actual)) return {
|
||||
code: testcase,
|
||||
};
|
||||
}
|
||||
result.code = "// (beautified)\n" + result.code;
|
||||
return result;
|
||||
}
|
||||
|
||||
function has_exit(fn) {
|
||||
var found = false;
|
||||
var tw = new U.TreeWalker(function(node) {
|
||||
|
||||
Reference in New Issue
Block a user