From 499f8d89ffd03f6f7d5b7235f4345516176e044b Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 7 Dec 2020 03:30:37 +0000 Subject: [PATCH] fix corner case in `inline` (#4336) fixes #4335 --- lib/compress.js | 38 ++++++++++++++++++++++++++------- test/compress/async.js | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index cf138377..005768b7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4638,7 +4638,7 @@ merge(Compressor.prototype, { if (self.name && self.name.definition() === fn.definition()) break; fn = fn.fixed_value(); } - if (!(fn instanceof AST_Lambda)) break; + if (!(fn instanceof AST_Defun || fn instanceof AST_Function)) break; if (fn.uses_arguments) break; if (fn === call.expression) { if (fn.parent_scope !== self) break; @@ -7776,7 +7776,9 @@ merge(Compressor.prototype, { var_assigned = true; if (stat) return false; } - } else if (line instanceof AST_Defun || line instanceof AST_EmptyStatement) { + } else if (line instanceof AST_AsyncDefun + || line instanceof AST_Defun + || line instanceof AST_EmptyStatement) { continue; } else if (stat) { return false; @@ -7803,6 +7805,7 @@ merge(Compressor.prototype, { var begin; var in_order = []; var side_effects = false; + var verify_await = true; value.walk(new TreeWalker(function(node, descend) { if (abort) return true; if (node instanceof AST_Binary && lazy_op[node.operator] @@ -7811,13 +7814,18 @@ merge(Compressor.prototype, { return; } if (node instanceof AST_Scope) return abort = true; + if (verify_await && node instanceof AST_Symbol && node.name == "await") { + var scope = compressor.find_parent(AST_Scope); + if (scope instanceof AST_AsyncDefun || scope instanceof AST_AsyncFunction) return abort = true; + verify_await = false; + } if (node instanceof AST_SymbolRef) { var def = node.definition(); if (fn.variables.get(node.name) !== def) { in_order = null; return; } - if (def.init instanceof AST_Defun) return abort = true; + if (def.init instanceof AST_AsyncDefun || def.init instanceof AST_Defun) return abort = true; if (is_lhs(node, this.parent())) return abort = true; var index = resolve_index(def); if (!(begin < index)) begin = index; @@ -7868,7 +7876,7 @@ merge(Compressor.prototype, { function can_inject_vars(defined, used, safe_to_inject) { for (var i = 0; i < fn.body.length; i++) { var stat = fn.body[i]; - if (stat instanceof AST_Defun) { + if (stat instanceof AST_AsyncDefun || stat instanceof AST_Defun) { if (!safe_to_inject || var_exists(used, stat.name.name)) return false; if (!all(stat.enclosed, function(def) { return def.scope === stat || !defined[def.name]; @@ -7890,7 +7898,7 @@ merge(Compressor.prototype, { var defined = Object.create(null); var level = 0, child; scope = compressor.self(); - while (!(scope instanceof AST_Scope)) { + do { if (scope.variables) scope.variables.each(function(def) { defined[def.name] = true; }); @@ -7908,11 +7916,25 @@ merge(Compressor.prototype, { } else if (scope instanceof AST_SymbolRef) { if (scope.fixed_value() instanceof AST_Scope) return false; } - } + } while (!(scope instanceof AST_Scope)); insert = scope.body.indexOf(child) + 1; if (!insert) return false; + if (scope instanceof AST_AsyncDefun || scope instanceof AST_AsyncFunction) { + var found = false; + fn.walk(new TreeWalker(function(node) { + if (found) return true; + if (node instanceof AST_Scope && node !== fn) { + if (node instanceof AST_AsyncDefun || node instanceof AST_Defun) { + if (node.name.name == "await") found = true; + } + return true; + } + if (node instanceof AST_Symbol && node.name == "await" && node !== fn.name) return found = true; + })); + if (found) return false; + } var safe_to_inject = (!(scope instanceof AST_Toplevel) || compressor.toplevel.vars) - && (exp !== fn || fn.parent_scope.resolve() === compressor.find_parent(AST_Scope)); + && (exp !== fn || fn.parent_scope.resolve() === scope); var inline = compressor.option("inline"); var used = Object.create(defined); if (!can_inject_args(defined, used, inline >= 2 && safe_to_inject)) return false; @@ -8004,7 +8026,7 @@ merge(Compressor.prototype, { flatten_vars(decls, expressions); expressions.push(value); var args = fn.body.filter(function(stat) { - if (stat instanceof AST_Defun) { + if (stat instanceof AST_AsyncDefun || stat instanceof AST_Defun) { var def = stat.name.definition(); scope.functions.set(def.name, def); scope.variables.set(def.name, def); diff --git a/test/compress/async.js b/test/compress/async.js index 2e4698d2..8da545bd 100644 --- a/test/compress/async.js +++ b/test/compress/async.js @@ -216,3 +216,51 @@ collapse_vars_3: { expect_stdout: "PASS" node_version: ">=8" } + +issue_4335_1: { + options = { + inline: true, + } + input: { + var await = "PASS"; + (async function() { + console.log(function() { + return await; + }()); + })(); + } + expect: { + var await = "PASS"; + (async function() { + console.log(function() { + return await; + }()); + })(); + } + expect_stdout: "PASS" + node_version: ">=8" +} + +issue_4335_2: { + options = { + inline: true, + } + input: { + (async function() { + console.log(function() { + function await() {} + return "PASS"; + }()); + })(); + } + expect: { + (async function() { + console.log(function() { + function await() {} + return "PASS"; + }()); + })(); + } + expect_stdout: "PASS" + node_version: ">=8" +} -- 2.34.1