aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-10-06 02:20:41 +0100
committerGitHub <noreply@github.com>2020-10-06 09:20:41 +0800
commitbc6e105174eb67547c2bd988899e4c4f2d8f6ada (patch)
tree723a511070cf6cd526c9ec0e8bc51f36b430a616
parentb91a2459c0f270b770c5d105df75f78c16af4749 (diff)
downloadtracifyjs-bc6e105174eb67547c2bd988899e4c4f2d8f6ada.tar.gz
tracifyjs-bc6e105174eb67547c2bd988899e4c4f2d8f6ada.zip
fix corner case in `ie8` (#4187)
fixes #4186
-rw-r--r--lib/ast.js3
-rw-r--r--lib/compress.js23
-rw-r--r--test/compress/functions.js51
-rw-r--r--test/compress/ie8.js40
-rw-r--r--test/reduce.js49
5 files changed, 129 insertions, 37 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 08b4b65c..ac779cb9 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -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, {
diff --git a/lib/compress.js b/lib/compress.js
index 8c28d450..29cc82a9 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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, {
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 3abfb30f..4e65b128 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -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"
+}
diff --git a/test/compress/ie8.js b/test/compress/ie8.js
index 4d74d44e..f2132579 100644
--- a/test/compress/ie8.js
+++ b/test/compress/ie8.js
@@ -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"
+}
diff --git a/test/reduce.js b/test/reduce.js
index 4ca88eff..f1d2b448 100644
--- a/test/reduce.js
+++ b/test/reduce.js
@@ -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) {