aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-08-25 18:26:49 +0100
committerGitHub <noreply@github.com>2020-08-26 01:26:49 +0800
commit09525c7530fb305c7b60c470ee9bab3510beb8f0 (patch)
treeb4f81bd4468597d1942fa028f45d932001fab448
parenta7e15fe73cb8d78e7590f2d11bf18bbfe41061ea (diff)
downloadtracifyjs-09525c7530fb305c7b60c470ee9bab3510beb8f0.tar.gz
tracifyjs-09525c7530fb305c7b60c470ee9bab3510beb8f0.zip
fix corner case in `sequences` (#4073)
-rw-r--r--lib/ast.js5
-rw-r--r--lib/compress.js28
-rw-r--r--test/compress/sequences.js45
3 files changed, 65 insertions, 13 deletions
diff --git a/lib/ast.js b/lib/ast.js
index b6d4ebb7..73f4696a 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -288,10 +288,13 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
var label = node.label;
var def = this.label;
node.walk(new TreeWalker(function(node) {
- if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
+ if (node instanceof AST_LoopControl) {
+ if (!node.label || node.label.thedef !== def) return;
node.label.thedef = label;
label.references.push(node);
+ return true;
}
+ if (node instanceof AST_Scope) return true;
}));
}
return node;
diff --git a/lib/compress.js b/lib/compress.js
index 3f0ea219..47445665 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -554,13 +554,6 @@ merge(Compressor.prototype, {
if (is_arguments(def) && node.property instanceof AST_Number) def.reassigned = true;
}
- var suppressor = new TreeWalker(function(node) {
- if (!(node instanceof AST_Symbol)) return;
- var d = node.definition();
- if (!d) return;
- if (node instanceof AST_SymbolRef) push_ref(d, node);
- d.fixed = false;
- });
def(AST_Accessor, function(tw, descend, compressor) {
push(tw);
reset_variables(tw, compressor, this);
@@ -740,11 +733,19 @@ merge(Compressor.prototype, {
return true;
});
def(AST_ForIn, function(tw) {
- this.init.walk(suppressor);
this.object.walk(tw);
var saved_loop = tw.in_loop;
tw.in_loop = this;
push(tw);
+ var init = this.init;
+ init.walk(tw);
+ if (init instanceof AST_Var) {
+ init = init.definitions[0].name;
+ } else while (init instanceof AST_PropAccess) {
+ init = init.expression.tail_node();
+ }
+ var def = init.definition();
+ if (def) def.fixed = false;
this.body.walk(tw);
pop(tw);
tw.in_loop = saved_loop;
@@ -8521,7 +8522,9 @@ merge(Compressor.prototype, {
}
}
if (is_lhs(compressor.self(), parent)) return self;
- if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+ if (compressor.option("sequences")
+ && parent.TYPE != "Call"
+ && !(parent instanceof AST_ForIn && parent.init === self)) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
@@ -8632,8 +8635,11 @@ merge(Compressor.prototype, {
col: self.start.col
});
}
- if (is_lhs(compressor.self(), compressor.parent())) return self;
- if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
+ var parent = compressor.parent();
+ if (is_lhs(compressor.self(), parent)) return self;
+ if (compressor.option("sequences")
+ && parent.TYPE != "Call"
+ && !(parent instanceof AST_ForIn && parent.init === self)) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index c0b77127..32db63d3 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -877,7 +877,7 @@ for_init_var: {
expect_stdout: "PASS"
}
-forin: {
+forin_1: {
options = {
sequences: true,
}
@@ -895,6 +895,49 @@ forin: {
expect_stdout: "PASS"
}
+forin_2: {
+ options = {
+ evaluate: true,
+ inline: true,
+ reduce_vars: true,
+ sequences: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var o = {
+ p: 1,
+ q: 2,
+ };
+ var k = "k";
+ for ((console.log("exp"), o)[function() {
+ console.log("prop");
+ return k;
+ }()] in function() {
+ console.log("obj");
+ return o;
+ }())
+ console.log(o.k, o[o.k]);
+ }
+ expect: {
+ var o = {
+ p: 1,
+ q: 2,
+ };
+ for ((console.log("exp"), o)[console.log("prop"), "k"] in console.log("obj"), o)
+ console.log(o.k, o[o.k]);
+ }
+ expect_stdout: [
+ "obj",
+ "exp",
+ "prop",
+ "p 1",
+ "exp",
+ "prop",
+ "q 2",
+ ]
+}
+
call: {
options = {
sequences: true,