aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-11-17 04:35:00 +0000
committerGitHub <noreply@github.com>2020-11-17 12:35:00 +0800
commit6dbacb5e3f4b3be40fab132575c2e5e3f820b32f (patch)
treec99062387272231d92dc598aeaa39fdfe9bce5aa
parente5f80afc53e7df3b0b57931a03dc3481ddd9c30e (diff)
downloadtracifyjs-6dbacb5e3f4b3be40fab132575c2e5e3f820b32f.tar.gz
tracifyjs-6dbacb5e3f4b3be40fab132575c2e5e3f820b32f.zip
enhance `varify` (#4279)
-rw-r--r--lib/compress.js52
-rw-r--r--test/compress/varify.js119
-rw-r--r--test/ufuzz/index.js2
3 files changed, 156 insertions, 17 deletions
diff --git a/lib/compress.js b/lib/compress.js
index d9446e87..7297938a 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -6551,6 +6551,19 @@ merge(Compressor.prototype, {
return if_break_in_loop(self, compressor);
});
+ OPT(AST_ForIn, function(self, compressor) {
+ if (compressor.option("varify") && (self.init instanceof AST_Const || self.init instanceof AST_Let)) {
+ var name = self.init.definitions[0].name;
+ if ((name instanceof AST_Destructured || name instanceof AST_SymbolLet)
+ && !name.match_symbol(function(node) {
+ if (node instanceof AST_SymbolDeclaration) return may_overlap(compressor, node.definition());
+ })) {
+ self.init = to_var(self.init);
+ }
+ }
+ return self;
+ });
+
function mark_locally_defined(condition, consequent, alternative) {
if (!(condition instanceof AST_Binary)) return;
if (!(condition.left instanceof AST_String)) {
@@ -7051,21 +7064,18 @@ merge(Compressor.prototype, {
return make_sequence(this, assignments);
});
- function varify(self, compressor) {
- return compressor.option("varify") && all(self.definitions, function(defn) {
- return !defn.name.match_symbol(function(node) {
- if (!(node instanceof AST_SymbolDeclaration)) return;
- if (!node.fixed_value()) return true;
- var def = node.definition();
- if (compressor.exposed(def)) return true;
- var scope = def.scope.resolve();
- for (var s = def.scope; s !== scope;) {
- s = s.parent_scope;
- if (s.var_names()[node.name]) return true;
- }
- });
- }) ? make_node(AST_Var, self, {
- definitions: self.definitions.map(function(defn) {
+ function may_overlap(compressor, def) {
+ if (compressor.exposed(def)) return true;
+ var scope = def.scope.resolve();
+ for (var s = def.scope; s !== scope;) {
+ s = s.parent_scope;
+ if (s.var_names()[def.name]) return true;
+ }
+ }
+
+ function to_var(stat) {
+ return make_node(AST_Var, stat, {
+ definitions: stat.definitions.map(function(defn) {
return make_node(AST_VarDef, defn, {
name: defn.name.convert_symbol(AST_SymbolVar, function(name, node) {
var def = name.definition();
@@ -7076,7 +7086,17 @@ merge(Compressor.prototype, {
value: defn.value
});
})
- }) : self;
+ });
+ }
+
+ function varify(self, compressor) {
+ return compressor.option("varify") && all(self.definitions, function(defn) {
+ return !defn.name.match_symbol(function(node) {
+ if (node instanceof AST_SymbolDeclaration) {
+ return !node.fixed_value() || may_overlap(compressor, node.definition());
+ }
+ });
+ }) ? to_var(self) : self;
}
OPT(AST_Const, varify);
diff --git a/test/compress/varify.js b/test/compress/varify.js
index 1286fc67..d4894d2d 100644
--- a/test/compress/varify.js
+++ b/test/compress/varify.js
@@ -234,3 +234,122 @@ issue_4191_let: {
expect_stdout: "function undefined"
node_version: ">=4"
}
+
+forin_const_1: {
+ options = {
+ join_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ varify: true,
+ }
+ input: {
+ const o = {
+ foo: 42,
+ bar: "PASS",
+ };
+ for (const k in o)
+ console.log(k, o[k]);
+ }
+ expect: {
+ var o = {
+ foo: 42,
+ bar: "PASS",
+ };
+ for (const k in o)
+ console.log(k, o[k]);
+ }
+ expect_stdout: true
+ node_version: ">=4"
+}
+
+forin_const_2: {
+ options = {
+ join_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ varify: true,
+ }
+ input: {
+ const o = {
+ p: 42,
+ q: "PASS",
+ };
+ for (const [ k ] in o)
+ console.log(k, o[k]);
+ }
+ expect: {
+ var o = {
+ p: 42,
+ q: "PASS",
+ }, k;
+ for ([ k ] in o)
+ console.log(k, o[k]);
+ }
+ expect_stdout: [
+ "p 42",
+ "q PASS",
+ ]
+ node_version: ">=6"
+}
+
+forin_let_1: {
+ options = {
+ join_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ varify: true,
+ }
+ input: {
+ "use strict";
+ let o = {
+ foo: 42,
+ bar: "PASS",
+ };
+ for (let k in o)
+ console.log(k, o[k]);
+ }
+ expect: {
+ "use strict";
+ var o = {
+ foo: 42,
+ bar: "PASS",
+ }, k;
+ for (k in o)
+ console.log(k, o[k]);
+ }
+ expect_stdout: [
+ "foo 42",
+ "bar PASS",
+ ]
+ node_version: ">=4"
+}
+
+forin_let_2: {
+ options = {
+ join_vars: true,
+ reduce_vars: true,
+ toplevel: true,
+ varify: true,
+ }
+ input: {
+ let o = {
+ p: 42,
+ q: "PASS",
+ };
+ for (let [ k ] in o)
+ console.log(k, o[k]);
+ }
+ expect: {
+ var o = {
+ p: 42,
+ q: "PASS",
+ }, k;
+ for ([ k ] in o)
+ console.log(k, o[k]);
+ }
+ expect_stdout: [
+ "p 42",
+ "q PASS",
+ ]
+ node_version: ">=6"
+}
diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js
index 1c4af3c3..70041966 100644
--- a/test/ufuzz/index.js
+++ b/test/ufuzz/index.js
@@ -708,7 +708,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
"{var expr" + loop + " = " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "; ",
label.target + " for (",
!/^key/.test(key) ? rng(10) ? "" : "var " : rng(10) ? "var " : rng(2) ? "let " : "const ",
- rng(20) ? key : "{ length: " + key + " }",
+ rng(10) ? key : rng(5) ? "[ " + key + " ]" : "{ length: " + key + " }",
" in expr" + loop + ") {",
rng(5) > 1 ? "c = 1 + c; var " + createVarName(MANDATORY) + " = expr" + loop + "[" + key + "]; " : "",
createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),