From 24443b676401005724defe2a4339944127656972 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 12 Jul 2022 16:49:43 +0100 Subject: [PATCH] enhance `collapse_vars` (#5556) --- lib/compress.js | 205 +++++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 99 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 587f0888fd..477115bb31 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1675,6 +1675,7 @@ Compressor.prototype.compress = function(node) { if (may_throw && parent.bcatch && parent.bcatch !== node) return true; } } + return false; } var identifier_atom = makePredicate("Infinity NaN undefined"); @@ -1917,7 +1918,7 @@ Compressor.prototype.compress = function(node) { var in_lambda = last_of(compressor, function(node) { return node instanceof AST_Lambda; }); - var block_scope, in_loop, in_try, scope; + var block_scope, iife_in_try, in_iife_single, in_loop, in_try, scope; find_loop_scope_try(); var changed, last_changed, max_iter = 10; do { @@ -2490,10 +2491,10 @@ Compressor.prototype.compress = function(node) { var after = stop_after; var if_hit = stop_if_hit; for (var i = 0; !abort && i < fn.argnames.length; i++) { - if (may_throw_arg(reject, fn.argnames[i], node.args[i])) abort = true; + if (arg_may_throw(reject, fn.argnames[i], node.args[i])) abort = true; } if (!abort) { - if (fn.rest && may_throw_arg(reject, fn.rest, make_node(AST_Array, node, { + if (fn.rest && arg_may_throw(reject, fn.rest, make_node(AST_Array, node, { elements: node.args.slice(i), }))) { abort = true; @@ -2579,128 +2580,134 @@ Compressor.prototype.compress = function(node) { } } - function may_throw_arg(reject, node, value) { + function arg_may_throw(reject, node, value) { if (node instanceof AST_DefaultValue) { return reject(node.value) - || may_throw_arg(reject, node.name, node.value) - || !is_undefined(value) && may_throw_arg(reject, node.name, value); + || arg_may_throw(reject, node.name, node.value) + || !is_undefined(value) && arg_may_throw(reject, node.name, value); } if (!value) return !(node instanceof AST_Symbol); if (node instanceof AST_Destructured) { - if (node.rest && may_throw_arg(reject, node.rest)) return true; + if (node.rest && arg_may_throw(reject, node.rest)) return true; if (node instanceof AST_DestructuredArray) { if (value instanceof AST_Array) return !all(node.elements, function(element, index) { - return !may_throw_arg(reject, element, value[index]); + return !arg_may_throw(reject, element, value[index]); }); return value.is_string(compressor) && !all(node.elements, function(element) { - return !may_throw_arg(reject, element); + return !arg_may_throw(reject, element); }); } if (node instanceof AST_DestructuredObject) { if (value.may_throw_on_access(compressor)) return true; return !all(node.properties, function(prop) { if (prop.key instanceof AST_Node && reject(prop.key)) return false; - return !may_throw_arg(reject, prop.value); + return !arg_may_throw(reject, prop.value); }); } } } function extract_args() { - var iife, fn = compressor.self(); - if (fn instanceof AST_LambdaExpression - && !is_generator(fn) - && !fn.uses_arguments - && !fn.pinned() - && (iife = compressor.parent()) instanceof AST_Call - && iife.expression === fn - && is_iife_single(iife) - && all(iife.args, function(arg) { - return !(arg instanceof AST_Spread); - })) { - var fn_strict = fn.in_strict_mode(compressor) - && !fn.parent_scope.resolve(true).in_strict_mode(compressor); - var check_arg = false, has_await; - if (is_async(fn)) { - check_arg = true; - has_await = function(node) { - return node instanceof AST_Symbol && node.name == "await"; - }; - } else { - check_arg = find_try(compressor, 1, iife, null, true, true); - has_await = function(node) { - return node instanceof AST_Await && !tw.find_parent(AST_Scope); - }; + if (in_iife_single === false) return; + var iife = compressor.parent(), fn = compressor.self(); + if (in_iife_single === undefined) { + if (!(fn instanceof AST_LambdaExpression) + || is_generator(fn) + || fn.uses_arguments + || fn.pinned() + || !(iife instanceof AST_Call) + || iife.expression !== fn + || !all(iife.args, function(arg) { + return !(arg instanceof AST_Spread); + })) { + in_iife_single = false; + return; } - var arg_scope = null; - var tw = new TreeWalker(function(node, descend) { - if (!arg) return true; - if (has_await(node) || node instanceof AST_Yield) { - arg = null; - return true; - } - if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) { - arg = null; - return true; - } - if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) { - var s = node.definition().scope; - if (s !== scope) while (s = s.parent_scope) { - if (s === scope) return true; - } - arg = null; - } - if (node instanceof AST_Scope && !is_arrow(node)) { - var save_scope = arg_scope; - arg_scope = node; - descend(); - arg_scope = save_scope; - return true; - } - }); - args = iife.args.slice(); - var len = args.length; - var names = new Dictionary(); - for (var i = fn.argnames.length; --i >= 0;) { - var sym = fn.argnames[i]; - var arg = args[i]; - var value = null; - if (sym instanceof AST_DefaultValue) { - value = sym.value; - sym = sym.name; - args[len + i] = value; - } - if (sym instanceof AST_Destructured) { - if (check_arg && may_throw_arg(function(node) { - return node.has_side_effects(compressor); - }, sym, arg)) { - candidates.length = 0; - break; - } - args[len + i] = fn.argnames[i]; - continue; + if (!is_iife_single(iife)) return; + in_iife_single = true; + } + var fn_strict = fn.in_strict_mode(compressor) + && !fn.parent_scope.resolve(true).in_strict_mode(compressor); + var has_await; + if (is_async(fn)) { + has_await = function(node) { + return node instanceof AST_Symbol && node.name == "await"; + }; + iife_in_try = true; + } else { + has_await = function(node) { + return node instanceof AST_Await && !tw.find_parent(AST_Scope); + }; + if (iife_in_try === undefined) iife_in_try = find_try(compressor, 1, iife, null, true, true); + } + var arg_scope = null; + var tw = new TreeWalker(function(node, descend) { + if (!arg) return true; + if (has_await(node) || node instanceof AST_Yield) { + arg = null; + return true; + } + if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) { + arg = null; + return true; + } + if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) { + var s = node.definition().scope; + if (s !== scope) while (s = s.parent_scope) { + if (s === scope) return true; } - if (names.has(sym.name)) continue; - names.set(sym.name, true); - if (value) arg = is_undefined(arg) ? value : null; - if (!arg && !value) { - arg = make_node(AST_Undefined, sym).transform(compressor); - } else if (arg instanceof AST_Lambda && arg.pinned()) { - arg = null; - } else if (arg) { - arg.walk(tw); + arg = null; + } + if (node instanceof AST_Scope && !is_arrow(node)) { + var save_scope = arg_scope; + arg_scope = node; + descend(); + arg_scope = save_scope; + return true; + } + }); + args = iife.args.slice(); + var len = args.length; + var names = new Dictionary(); + for (var i = fn.argnames.length; --i >= 0;) { + var sym = fn.argnames[i]; + var arg = args[i]; + var value = null; + if (sym instanceof AST_DefaultValue) { + value = sym.value; + sym = sym.name; + args[len + i] = value; + } + if (sym instanceof AST_Destructured) { + if (iife_in_try && arg_may_throw(function(node) { + return node.has_side_effects(compressor); + }, sym, arg)) { + candidates.length = 0; + break; } - if (!arg) continue; - var candidate = make_node(AST_VarDef, sym, { - name: sym, - value: arg, - }); - candidate.name_index = i; - candidate.arg_index = value ? len + i : i; - candidates.unshift([ candidate ]); + args[len + i] = fn.argnames[i]; + continue; } - if (fn.rest) args.push(fn.rest); + if (names.has(sym.name)) continue; + names.set(sym.name, true); + if (value) arg = is_undefined(arg) ? value : null; + if (!arg && !value) { + arg = make_node(AST_Undefined, sym).transform(compressor); + } else if (arg instanceof AST_Lambda && arg.pinned()) { + arg = null; + } else if (arg) { + arg.walk(tw); + } + if (!arg) continue; + var candidate = make_node(AST_VarDef, sym, { + name: sym, + value: arg, + }); + candidate.name_index = i; + candidate.arg_index = value ? len + i : i; + candidates.unshift([ candidate ]); } + if (fn.rest) args.push(fn.rest); } function extract_candidates(expr, unused) {