From 972b9f0bef90844a522f777610e88bf113309025 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 3 Jul 2021 23:19:08 +0100 Subject: [PATCH] enhance `functions` & `reduce_vars` (#5045) --- lib/compress.js | 331 ++++++++++++++++++++-------------- test/compress/arrows.js | 32 ++++ test/compress/drop-unused.js | 3 +- test/compress/functions.js | 2 + test/compress/hoist_vars.js | 3 +- test/compress/let.js | 35 ++++ test/compress/pure_getters.js | 1 + test/compress/reduce_vars.js | 37 ++-- test/reduce.js | 2 +- 9 files changed, 286 insertions(+), 160 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index ea431f13e13..8045cecf332 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -484,9 +484,21 @@ merge(Compressor.prototype, { def.single_use = undefined; } + function reset_block_variables(tw, compressor, scope) { + scope.variables.each(function(def) { + reset_def(tw, compressor, def); + }); + } + function reset_variables(tw, compressor, scope) { + scope.fn_defs = []; scope.variables.each(function(def) { reset_def(tw, compressor, def); + var init = def.init; + if (init instanceof AST_LambdaDefinition) { + scope.fn_defs.push(init); + init.safe_ids = null; + } if (def.fixed === null) { def.safe_ids = tw.safe_ids; mark(tw, def); @@ -496,13 +508,7 @@ merge(Compressor.prototype, { } }); scope.may_call_this = function() { - scope.may_call_this = noop; - if (!scope.contains_this()) return; - scope.functions.each(function(def) { - if (def.init instanceof AST_LambdaDefinition && !(def.id in tw.defun_ids)) { - tw.defun_ids[def.id] = false; - } - }); + scope.may_call_this = scope.contains_this() ? return_true : return_false; }; if (scope.uses_arguments) scope.each_argname(function(node) { node.definition().last_ref = false; @@ -513,39 +519,56 @@ merge(Compressor.prototype, { }); } - function mark_defun(tw, def) { - if (def.id in tw.defun_ids) { - var marker = tw.defun_ids[def.id]; - if (!marker) return; - var visited = tw.defun_visited[def.id]; - if (marker === tw.safe_ids) return !visited && def.fixed; + function mark_fn_def(tw, def, fn) { + if (!HOP(fn, "safe_ids")) return; + var marker = fn.safe_ids; + if (marker === false) return; + if (fn.parent_scope.resolve().may_call_this === return_true) return; + if (marker) { + var visited = member(fn, tw.fn_visited); + if (marker === tw.safe_ids) return !visited && fn; if (visited) { - def.init.enclosed.forEach(function(d) { - if (def.init.variables.get(d.name) === d) return; - if (!safe_to_read(tw, d)) d.fixed = false; + fn.enclosed.forEach(function(d) { + if (fn.variables.get(d.name) === d) return; + if (safe_to_read(tw, d)) return; + d.single_use = false; + if (d.fixed instanceof AST_LambdaDefinition) return; + d.fixed = false; }); return; } - } else if (!tw.in_loop) { - var scope = def.scope; - var s = tw.find_parent(AST_Scope); - do { - if (s === scope) { - tw.defun_ids[def.id] = tw.safe_ids; - return def.fixed; - } - } while (s instanceof AST_LambdaExpression && (s = s.parent_scope.resolve())); + } else if (!tw.in_loop && !(tw.fn_scanning && tw.fn_scanning !== def.scope.resolve())) { + fn.safe_ids = tw.safe_ids; + return fn; } - tw.defun_ids[def.id] = false; + fn.safe_ids = false; } - function walk_defuns(tw, scope) { - scope.functions.each(function(def) { - if (def.init instanceof AST_LambdaDefinition && !tw.defun_visited[def.id]) { - tw.defun_ids[def.id] = tw.safe_ids; - def.init.walk(tw); - } + function walk_fn_def(tw, fn) { + var was_scanning = tw.fn_scanning; + tw.fn_scanning = fn; + fn.walk(tw); + tw.fn_scanning = was_scanning; + } + + function pop_scope(tw, scope) { + var fn_defs = scope.fn_defs; + var tangled = scope.may_call_this === return_true ? fn_defs : fn_defs.filter(function(fn) { + if (fn.safe_ids === false) return true; + fn.safe_ids = tw.safe_ids; + walk_fn_def(tw, fn); + return false; }); + pop(tw); + tangled.forEach(function(fn) { + fn.safe_ids = tw.safe_ids; + walk_fn_def(tw, fn); + }); + fn_defs.forEach(function(fn) { + delete fn.safe_ids; + }); + delete scope.fn_defs; + delete scope.may_call_this; } function push(tw) { @@ -592,13 +615,13 @@ merge(Compressor.prototype, { if (def.fixed === undefined) return declare || all(def.orig, function(sym) { return !(sym instanceof AST_SymbolLet); }); - if (def.fixed === null && def.safe_ids) { + if (def.fixed === false) return false; + var safe = tw.safe_ids[def.id]; + if (def.safe_ids) { def.safe_ids[def.id] = false; delete def.safe_ids; - return true; + return def.fixed === null || HOP(tw.safe_ids, def.id) && !safe.read; } - if (def.fixed === false) return false; - var safe = tw.safe_ids[def.id]; if (!HOP(tw.safe_ids, def.id)) { if (!safe) return false; if (safe.read) { @@ -813,8 +836,7 @@ merge(Compressor.prototype, { }, visit); walk_lambda(fn, tw); var safe_ids = tw.safe_ids; - pop(tw); - walk_defuns(tw, fn); + pop_scope(tw, fn); if (!aborts) tw.safe_ids = safe_ids; return true; @@ -835,7 +857,8 @@ merge(Compressor.prototype, { var node = this; var left = node.left; var right = node.right; - var scan = left instanceof AST_Destructured || left instanceof AST_SymbolRef; + var ld = left instanceof AST_SymbolRef && left.definition(); + var scan = ld || left instanceof AST_Destructured; switch (node.operator) { case "=": if (left.equivalent_to(right) && !left.has_side_effects(compressor)) { @@ -844,7 +867,17 @@ merge(Compressor.prototype, { node.__drop = true; return true; } - if (scan) { + if (ld && right instanceof AST_LambdaExpression) { + walk_assign(); + if (ld.escaped.length) { + right.walk(tw); + } else { + right.parent_scope.resolve().fn_defs.push(right); + right.safe_ids = null; + } + return true; + } else if (scan) { + right.walk(tw); walk_assign(); return true; } @@ -856,6 +889,7 @@ merge(Compressor.prototype, { left.walk(tw); push(tw); if (scan) { + right.walk(tw); walk_assign(); } else { mark_assignment_to_arguments(left); @@ -868,20 +902,19 @@ merge(Compressor.prototype, { mark_assignment_to_arguments(left); return; } - var d = left.definition(); - d.assignments++; - var fixed = d.fixed; + ld.assignments++; + var fixed = ld.fixed; if (is_modified(compressor, tw, node, node, 0)) { - d.fixed = false; + ld.fixed = false; return; } - var safe = safe_to_read(tw, d); + var safe = safe_to_read(tw, ld); right.walk(tw); - if (safe && !left.in_arg && safe_to_assign(tw, d)) { - push_ref(d, left); - mark(tw, d); - if (d.single_use) d.single_use = false; - left.fixed = d.fixed = function() { + if (safe && !left.in_arg && safe_to_assign(tw, ld)) { + push_ref(ld, left); + mark(tw, ld); + if (ld.single_use) ld.single_use = false; + left.fixed = ld.fixed = function() { return make_node(AST_Binary, node, { operator: node.operator.slice(0, -1), left: make_ref(left, fixed), @@ -892,7 +925,7 @@ merge(Compressor.prototype, { left.fixed.assigns.push(node); } else { left.walk(tw); - d.fixed = false; + ld.fixed = false; } return true; } @@ -920,8 +953,8 @@ merge(Compressor.prototype, { } function walk_assign() { - right.walk(tw); - var modified = is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive_ref(tw, d)); + var recursive = ld && recursive_ref(tw, ld); + var modified = is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive); scan_declaration(tw, compressor, left, function() { return node.right; }, function(sym, fixed, walk) { @@ -956,9 +989,7 @@ merge(Compressor.prototype, { return true; }); def(AST_BlockScope, function(tw, descend, compressor) { - this.variables.each(function(def) { - reset_def(tw, compressor, def); - }); + reset_block_variables(tw, compressor, this); }); def(AST_Call, function(tw, descend) { var node = this; @@ -969,43 +1000,43 @@ merge(Compressor.prototype, { arg.walk(tw); if (arg instanceof AST_Spread) iife = false; }); - if (iife) exp.reduce_vars = reduce_iife; + if (iife) { + exp.reduce_vars = reduce_iife; + } else { + exp.safe_ids = tw.safe_ids; + } exp.walk(tw); if (iife) delete exp.reduce_vars; return true; } - var def = exp instanceof AST_SymbolRef && exp.definition(); if (node.TYPE == "Call" && tw.in_boolean_context()) { - if (def) { - def.bool_fn++; + if (exp instanceof AST_SymbolRef) { + exp.definition().bool_fn++; } else if (exp instanceof AST_Assign && exp.operator == "=" && exp.left instanceof AST_SymbolRef) { exp.left.definition().bool_fn++; } } - if (def && def.fixed instanceof AST_LambdaDefinition) { - var defun = mark_defun(tw, def); - if (defun) { - descend(); - defun.walk(tw); - return true; - } + exp.walk(tw); + var fixed = exp instanceof AST_SymbolRef && exp.fixed_value(); + var optional = node.optional; + var fn; + if (fixed instanceof AST_Lambda) { + fn = mark_fn_def(tw, exp.definition(), fixed); + optional = false; } else { tw.find_parent(AST_Scope).may_call_this(); } - if (!node.optional) return; - exp.walk(tw); - push(tw); + if (optional) push(tw); node.args.forEach(function(arg) { arg.walk(tw); }); - pop(tw); + if (optional) pop(tw); + if (fn) walk_fn_def(tw, fn); return true; }); def(AST_Class, function(tw, descend, compressor) { var node = this; - node.variables.each(function(def) { - reset_def(tw, compressor, def); - }); + reset_block_variables(tw, compressor, node); if (node.extends) node.extends.walk(tw); var props = node.properties.filter(function(prop) { reset_flags(prop); @@ -1057,7 +1088,7 @@ merge(Compressor.prototype, { return true; }); def(AST_Do, function(tw) { - var saved_loop = tw.in_loop; + var save_loop = tw.in_loop; tw.in_loop = this; push(tw); this.body.walk(tw); @@ -1067,39 +1098,37 @@ merge(Compressor.prototype, { } this.condition.walk(tw); pop(tw); - tw.in_loop = saved_loop; + tw.in_loop = save_loop; return true; }); def(AST_For, function(tw, descend, compressor) { - this.variables.each(function(def) { - reset_def(tw, compressor, def); - }); - if (this.init) this.init.walk(tw); - var saved_loop = tw.in_loop; - tw.in_loop = this; + var node = this; + reset_block_variables(tw, compressor, node); + if (node.init) node.init.walk(tw); + var save_loop = tw.in_loop; + tw.in_loop = node; push(tw); - if (this.condition) this.condition.walk(tw); - this.body.walk(tw); - if (this.step) { - if (has_loop_control(this, tw.parent())) { + if (node.condition) node.condition.walk(tw); + node.body.walk(tw); + if (node.step) { + if (has_loop_control(node, tw.parent())) { pop(tw); push(tw); } - this.step.walk(tw); + node.step.walk(tw); } pop(tw); - tw.in_loop = saved_loop; + tw.in_loop = save_loop; return true; }); def(AST_ForEnumeration, function(tw, descend, compressor) { - this.variables.each(function(def) { - reset_def(tw, compressor, def); - }); - this.object.walk(tw); - var saved_loop = tw.in_loop; - tw.in_loop = this; + var node = this; + reset_block_variables(tw, compressor, node); + node.object.walk(tw); + var save_loop = tw.in_loop; + tw.in_loop = node; push(tw); - var init = this.init; + var init = node.init; if (init instanceof AST_Definitions) { init.definitions[0].name.mark_symbol(function(node) { if (node instanceof AST_SymbolDeclaration) { @@ -1120,9 +1149,9 @@ merge(Compressor.prototype, { } else { init.walk(tw); } - this.body.walk(tw); + node.body.walk(tw); pop(tw); - tw.in_loop = saved_loop; + tw.in_loop = save_loop; return true; }); def(AST_If, function(tw) { @@ -1145,13 +1174,14 @@ merge(Compressor.prototype, { }); def(AST_Lambda, function(tw, descend, compressor) { var fn = this; + if (HOP(fn, "safe_ids") && fn.safe_ids !== tw.safe_ids) return true; + if (!push_uniq(tw.fn_visited, fn)) return true; fn.inlined = false; push(tw); reset_variables(tw, compressor, fn); descend(); - pop(tw); + pop_scope(tw, fn); if (fn.name) mark_escaped(tw, fn.name.definition(), fn, fn.name, fn, 0, 1); - walk_defuns(tw, fn); return true; }); def(AST_LambdaDefinition, function(tw, descend, compressor) { @@ -1159,15 +1189,13 @@ merge(Compressor.prototype, { var def = fn.name.definition(); var parent = tw.parent(); if (parent instanceof AST_ExportDeclaration || parent instanceof AST_ExportDefault) def.single_use = false; - if (tw.defun_visited[def.id]) return true; - if (def.init === fn && tw.defun_ids[def.id] !== tw.safe_ids) return true; - tw.defun_visited[def.id] = true; + if (HOP(fn, "safe_ids") && fn.safe_ids !== tw.safe_ids) return true; + if (!push_uniq(tw.fn_visited, fn)) return true; fn.inlined = false; push(tw); reset_variables(tw, compressor, fn); descend(); - pop(tw); - walk_defuns(tw, fn); + pop_scope(tw, fn); return true; }); def(AST_Sub, function(tw) { @@ -1179,12 +1207,11 @@ merge(Compressor.prototype, { return true; }); def(AST_Switch, function(tw, descend, compressor) { - this.variables.each(function(def) { - reset_def(tw, compressor, def); - }); - this.expression.walk(tw); + var node = this; + reset_block_variables(tw, compressor, node); + node.expression.walk(tw); var first = true; - this.body.forEach(function(branch) { + node.body.forEach(function(branch) { if (branch instanceof AST_Default) return; branch.expression.walk(tw); if (first) { @@ -1193,7 +1220,7 @@ merge(Compressor.prototype, { } }) if (!first) pop(tw); - walk_body(this, tw); + walk_body(node, tw); return true; }); def(AST_SwitchBranch, function(tw) { @@ -1258,36 +1285,62 @@ merge(Compressor.prototype, { } if (!this.fixed) this.fixed = d.fixed; var parent; - if (d.fixed instanceof AST_LambdaDefinition + if (value instanceof AST_Lambda && !((parent = tw.parent()) instanceof AST_Call && parent.expression === this)) { - var defun = mark_defun(tw, d); - if (defun) defun.walk(tw); + var fn = mark_fn_def(tw, d, value); + if (fn) walk_fn_def(tw, fn); + } + }); + def(AST_Template, function(tw, descend) { + var node = this; + var tag = node.tag; + if (!tag) return; + if (tag instanceof AST_LambdaExpression) { + node.expressions.forEach(function(exp) { + exp.walk(tw); + }); + tag.safe_ids = tw.safe_ids; + tag.walk(tw); + delete tag.reduce_vars; + return true; } + tag.walk(tw); + var fixed = tag instanceof AST_SymbolRef && tag.fixed_value(); + var fn; + if (fixed instanceof AST_Lambda) { + fn = mark_fn_def(tw, tag.definition(), fixed); + } else { + tw.find_parent(AST_Scope).may_call_this(); + } + node.expressions.forEach(function(exp) { + exp.walk(tw); + }); + if (fn) walk_fn_def(tw, fn); + return true; }); def(AST_Toplevel, function(tw, descend, compressor) { - this.globals.each(function(def) { + var node = this; + node.globals.each(function(def) { reset_def(tw, compressor, def); }); push(tw); - reset_variables(tw, compressor, this); + reset_variables(tw, compressor, node); descend(); - pop(tw); - walk_defuns(tw, this); + pop_scope(tw, node); return true; }); def(AST_Try, function(tw, descend, compressor) { - this.variables.each(function(def) { - reset_def(tw, compressor, def); - }); + var node = this; + reset_block_variables(tw, compressor, node); push(tw); - walk_body(this, tw); + walk_body(node, tw); pop(tw); - if (this.bcatch) { + if (node.bcatch) { push(tw); - this.bcatch.walk(tw); + node.bcatch.walk(tw); pop(tw); } - if (this.bfinally) this.bfinally.walk(tw); + if (node.bfinally) node.bfinally.walk(tw); return true; }); def(AST_Unary, function(tw, descend) { @@ -1338,8 +1391,12 @@ merge(Compressor.prototype, { }); def(AST_VarDef, function(tw, descend, compressor) { var node = this; - if (node.value) { - node.value.walk(tw); + var value = node.value; + if (value instanceof AST_LambdaExpression && node.name instanceof AST_SymbolDeclaration) { + value.parent_scope.resolve().fn_defs.push(value); + value.safe_ids = null; + } else if (value) { + value.walk(tw); } else if (!(tw.parent() instanceof AST_Let)) { return; } @@ -1363,12 +1420,12 @@ merge(Compressor.prototype, { return true; }); def(AST_While, function(tw, descend) { - var saved_loop = tw.in_loop; + var save_loop = tw.in_loop; tw.in_loop = this; push(tw); descend(); pop(tw); - tw.in_loop = saved_loop; + tw.in_loop = save_loop; return true; }); })(function(node, func) { @@ -1387,9 +1444,9 @@ merge(Compressor.prototype, { reset_flags(node); return node.reduce_vars(tw, descend, compressor); } : reset_flags); - // Flow control for visiting `AST_Defun`s - tw.defun_ids = Object.create(null); - tw.defun_visited = Object.create(null); + // Flow control for visiting lambda definitions + tw.fn_scanning = null; + tw.fn_visited = []; // Record the loop body in which `AST_SymbolDeclaration` is first encountered tw.in_loop = null; tw.loop_ids = Object.create(null); @@ -1642,9 +1699,7 @@ merge(Compressor.prototype, { return all(block.body, function(stat) { return is_empty(stat) || stat instanceof AST_Defun - || stat instanceof AST_Var && all(stat.definitions, function(var_def) { - return !var_def.value; - }); + || stat instanceof AST_Var && declarations_only(stat); }); } @@ -6468,7 +6523,7 @@ merge(Compressor.prototype, { } } else if (compressor.option("functions") && !compressor.option("ie8") - && node instanceof AST_Var + && drop_sym && var_defs[sym.id] == 1 && sym.assignments == 0 && value instanceof AST_LambdaExpression @@ -6542,7 +6597,7 @@ merge(Compressor.prototype, { } function can_declare_defun(fn) { - if (compressor.has_directive("use strict") || !(fn instanceof AST_Function)) { + if (!is_var || compressor.has_directive("use strict") || !(fn instanceof AST_Function)) { return parent instanceof AST_Scope; } return parent instanceof AST_Block @@ -9501,9 +9556,7 @@ merge(Compressor.prototype, { for (var i = 0; i < len; i++) { var line = fn.body[i]; if (line instanceof AST_Var) { - var assigned = var_assigned || !all(line.definitions, function(var_def) { - return !var_def.value; - }); + var assigned = var_assigned || !declarations_only(line); if (assigned) { var_assigned = true; if (stat) return false; diff --git a/test/compress/arrows.js b/test/compress/arrows.js index be869512978..abbbbf9004e 100644 --- a/test/compress/arrows.js +++ b/test/compress/arrows.js @@ -556,6 +556,38 @@ reduce_iife_3: { node_version: ">=4" } +reduce_lambda: { + options = { + evaluate: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var f = () => { + console.log(a, b); + }; + var a = "foo", b = 42; + f(); + b = "bar"; + f(); + } + expect: { + var f = () => { + console.log("foo", b); + }; + var b = 42; + f(); + b = "bar"; + f(); + } + expect_stdout: [ + "foo 42", + "foo bar", + ] + node_version: ">=4" +} + single_use_recursive: { options = { reduce_vars: true, diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 4c2ffecea32..ed821c298a4 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -3081,7 +3081,8 @@ issue_4235: { } expect: { void function() { - var f = console.log(f); + var f; + console.log(f); }(); } expect_stdout: "undefined" diff --git a/test/compress/functions.js b/test/compress/functions.js index e4766cd5c7e..cad6e5e4261 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -2905,6 +2905,7 @@ issue_2437: { issue_2485_1: { options = { functions: true, + passes: 2, reduce_funcs: true, reduce_vars: true, unused: true, @@ -2955,6 +2956,7 @@ issue_2485_2: { options = { functions: true, inline: true, + passes: 2, reduce_funcs: true, reduce_vars: true, unused: true, diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js index fe39cdde4db..97987fd9e7f 100644 --- a/test/compress/hoist_vars.js +++ b/test/compress/hoist_vars.js @@ -152,7 +152,8 @@ issue_4487: { } expect: { function a() { - var f = console.log(typeof f); + var f; + console.log(typeof f); } a(); } diff --git a/test/compress/let.js b/test/compress/let.js index 0a23f65b1e8..59e60ae071b 100644 --- a/test/compress/let.js +++ b/test/compress/let.js @@ -494,6 +494,41 @@ reduce_vars_3: { node_version: ">=4" } +reduce_lambda: { + options = { + evaluate: true, + functions: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + "use strict"; + let f = function() { + console.log(a, b); + }; + let a = "foo", b = 42; + f(); + b = "bar"; + f(); + } + expect: { + "use strict"; + function f() { + console.log("foo", b); + } + let b = 42; + f(); + b = "bar"; + f(); + } + expect_stdout: [ + "foo 42", + "foo bar", + ] + node_version: ">=4" +} + hoist_props: { options = { hoist_props: true, diff --git a/test/compress/pure_getters.js b/test/compress/pure_getters.js index 935b3e31e46..ad2117cc929 100644 --- a/test/compress/pure_getters.js +++ b/test/compress/pure_getters.js @@ -1320,6 +1320,7 @@ issue_2878: { issue_3427: { options = { + assignments: true, evaluate: true, inline: true, pure_getters: "strict", diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 69f8652330e..c1531b25487 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -3092,7 +3092,7 @@ accessor_1: { a = 2; return a; }, - b: 1 + b: 1, }.b, a); } expect: { @@ -3102,7 +3102,7 @@ accessor_1: { a = 2; return a; }, - b: 1 + b: 1, }.b, a); } expect_stdout: "1 1" @@ -3122,7 +3122,7 @@ accessor_2: { var B = { get c() { console.log(A); - } + }, }; B.c; } @@ -3130,7 +3130,7 @@ accessor_2: { ({ get c() { console.log(1); - } + }, }).c; } expect_stdout: "1" @@ -3176,7 +3176,7 @@ obj_var_1: { var obj = { bar: function() { return C + C; - } + }, }; console.log(obj.bar()); } @@ -3184,7 +3184,7 @@ obj_var_1: { console.log({ bar: function() { return 2; - } + }, }.bar()); } expect_stdout: "2" @@ -3208,7 +3208,7 @@ obj_var_2: { var obj = { bar: function() { return C + C; - } + }, }; console.log(obj.bar()); } @@ -4422,6 +4422,7 @@ perf_2: { perf_3: { options = { + passes: 2, reduce_funcs: true, reduce_vars: true, toplevel: true, @@ -4430,10 +4431,10 @@ perf_3: { input: { var foo = function(x, y, z) { return x < y ? x * y + z : x * z - y; - } + }; var indirect_foo = function(x, y, z) { return foo(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); @@ -4462,10 +4463,10 @@ perf_4: { input: { var foo = function(x, y, z) { return x < y ? x * y + z : x * z - y; - } + }; var indirect_foo = function(x, y, z) { return foo(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); @@ -4474,10 +4475,10 @@ perf_4: { expect: { var foo = function(x, y, z) { return x < y ? x * y + z : x * z - y; - } + }; var indirect_foo = function(x, y, z) { return foo(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); @@ -4566,9 +4567,9 @@ perf_7: { var indirect_foo = function(x, y, z) { var foo = function(x, y, z) { return x < y ? x * y + z : x * z - y; - } + }; return foo(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); @@ -4598,9 +4599,9 @@ perf_8: { var indirect_foo = function(x, y, z) { var foo = function(x, y, z) { return x < y ? x * y + z : x * z - y; - } + }; return foo(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); @@ -4611,7 +4612,7 @@ perf_8: { return function(x, y, z) { return x < y ? x * y + z : x * z - y; }(x, y, z); - } + }; var sum = 0; for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i); diff --git a/test/reduce.js b/test/reduce.js index 15f869e5bd1..398b74a54f1 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -726,7 +726,7 @@ function to_statement_init(node) { return node instanceof U.AST_Const || node instanceof U.AST_Let ? new U.AST_BlockStatement({ body: [ node ], start: {}, - }) : to_statement(node);; + }) : to_statement(node); } function wrap_with_console_log(node) {