aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2019-11-27 17:35:21 +0800
committerGitHub <noreply@github.com>2019-11-27 17:35:21 +0800
commitd4b701067805f5041c3b27225742a7b36c3db90c (patch)
tree6d43085a36f7eafcdcf217b717e46c8ca2c92ac2
parente27493f3c2e637b8f3e9da4757e76959a8705cd9 (diff)
downloadtracifyjs-d4b701067805f5041c3b27225742a7b36c3db90c.tar.gz
tracifyjs-d4b701067805f5041c3b27225742a7b36c3db90c.zip
fix corner case in `unsafe_regexp` (#3609)
-rw-r--r--lib/compress.js18
-rw-r--r--test/compress/collapse_vars.js46
-rw-r--r--test/compress/evaluate.js104
3 files changed, 157 insertions, 11 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 46a7816e..19fba0b6 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 abdd9c2a..0f1e59a3 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 94258049..09fdfb2a 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",
+ ]
+}