diff --git a/lib/compress.js b/lib/compress.js index 46a7816e2c..19fba0b6fb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -362,6 +362,7 @@ merge(Compressor.prototype, { function reset_def(tw, compressor, def) { def.assignments = 0; def.chained = false; + def.cross_loop = false; def.direct_access = false; def.escaped = []; def.fixed = !def.scope.pinned() @@ -765,6 +766,9 @@ merge(Compressor.prototype, { d.fixed = false; } } + if (d.fixed && tw.loop_ids[d.id] !== tw.in_loop) { + d.cross_loop = true; + } mark_escaped(tw, d, this.scope, this, value, 0, 1); } var parent; @@ -6494,14 +6498,13 @@ merge(Compressor.prototype, { if (fixed && def.should_replace === undefined) { var init; if (fixed instanceof AST_This) { - if (!(def.orig[0] instanceof AST_SymbolFunarg) && all(def.references, function(ref) { - return def.scope === ref.scope; - })) { + if (!(def.orig[0] instanceof AST_SymbolFunarg) && same_scope(def)) { init = fixed; } } else { var ev = fixed.evaluate(compressor); - if (ev !== fixed && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))) { + if (ev !== fixed && (!(ev instanceof RegExp) + || compressor.option("unsafe_regexp") && !def.cross_loop && same_scope(def))) { init = make_node_from_constant(ev, fixed); } } @@ -6538,6 +6541,13 @@ merge(Compressor.prototype, { } return self; + function same_scope(def) { + var scope = def.scope.resolve(); + return all(def.references, function(ref) { + return scope === ref.scope.resolve(); + }); + } + function has_symbol_ref(value) { var found; value.walk(new TreeWalker(function(node) { diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index abdd9c2ae9..0f1e59a383 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -1633,21 +1633,32 @@ collapse_vars_regexp: { return rx.exec(s); }; } + function f3() { + var rx = /ab*/g; + return function() { + return rx; + }; + } (function() { var result; - var s = 'acdabcdeabbb'; + var s = "acdabcdeabbb"; var rx = /ab*/g; - while (result = rx.exec(s)) { + while (result = rx.exec(s)) console.log(result[0]); - } })(); (function() { var result; - var s = 'acdabcdeabbb'; + var s = "acdabcdeabbb"; var rx = f2(); - while (result = rx(s)) { + while (result = rx(s)) + console.log(result[0]); + })(); + (function() { + var result; + var s = "acdabcdeabbb"; + var rx = f3(); + while (result = rx().exec(s)) console.log(result[0]); - } })(); } expect: { @@ -1660,6 +1671,12 @@ collapse_vars_regexp: { return rx.exec(s); }; } + function f3() { + var rx = /ab*/g; + return function() { + return rx; + }; + } (function() { var result, rx = /ab*/g; while (result = rx.exec("acdabcdeabbb")) @@ -1670,8 +1687,23 @@ collapse_vars_regexp: { while (result = rx("acdabcdeabbb")) console.log(result[0]); })(); + (function() { + var result, rx = f3(); + while (result = rx().exec("acdabcdeabbb")) + console.log(result[0]); + })(); } - expect_stdout: true + expect_stdout: [ + "a", + "ab", + "abbb", + "a", + "ab", + "abbb", + "a", + "ab", + "abbb", + ] } issue_1537: { diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js index 94258049ac..09fdfb2ad3 100644 --- a/test/compress/evaluate.js +++ b/test/compress/evaluate.js @@ -2057,3 +2057,107 @@ threshold_evaluate_999: { } expect_stdout: "111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK" } + +collapse_vars_regexp: { + options = { + booleans: true, + collapse_vars: true, + comparisons: true, + conditionals: true, + dead_code: true, + evaluate: true, + hoist_funs: true, + if_return: true, + join_vars: true, + keep_fargs: true, + loops: false, + reduce_funcs: true, + reduce_vars: true, + side_effects: true, + unsafe_regexp: true, + unused: true, + } + input: { + function f1() { + var k = 9; + var rx = /[A-Z]+/; + return [rx, k]; + } + function f2() { + var rx = /ab*/g; + return function(s) { + return rx.exec(s); + }; + } + function f3() { + var rx = /ab*/g; + return function() { + return rx; + }; + } + (function() { + var result; + var s = "acdabcdeabbb"; + var rx = /ab*/g; + while (result = rx.exec(s)) + console.log(result[0]); + })(); + (function() { + var result; + var s = "acdabcdeabbb"; + var rx = f2(); + while (result = rx(s)) + console.log(result[0]); + })(); + (function() { + var result; + var s = "acdabcdeabbb"; + var rx = f3(); + while (result = rx().exec(s)) + console.log(result[0]); + })(); + } + expect: { + function f1() { + return [/[A-Z]+/, 9]; + } + function f2() { + var rx = /ab*/g; + return function(s) { + return rx.exec(s); + }; + } + function f3() { + var rx = /ab*/g; + return function() { + return rx; + }; + } + (function() { + var result, rx = /ab*/g; + while (result = rx.exec("acdabcdeabbb")) + console.log(result[0]); + })(); + (function() { + var result, rx = f2(); + while (result = rx("acdabcdeabbb")) + console.log(result[0]); + })(); + (function() { + var result, rx = f3(); + while (result = rx().exec("acdabcdeabbb")) + console.log(result[0]); + })(); + } + expect_stdout: [ + "a", + "ab", + "abbb", + "a", + "ab", + "abbb", + "a", + "ab", + "abbb", + ] +}