[Pkg-javascript-commits] [uglifyjs] 264/491: consolidate & enhance `unused` (#2439)
Jonas Smedegaard
dr at jones.dk
Wed Feb 14 19:51:42 UTC 2018
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.
commit 6c4510187066555c77003f03fd26e2cf5ff47491
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date: Mon Nov 6 14:25:10 2017 +0800
consolidate & enhance `unused` (#2439)
- defer declaration removal in `collapse_vars`
- account for `AST_SymbolFunarg` in deduplication
- private accounting for `collapse_vars`
- avoid issues with identity reference due to deep cloning
fixes #2437
---
lib/compress.js | 142 +++++++++++++++++++++--------------------
test/compress/collapse_vars.js | 66 ++++++++++++++++++-
test/compress/issue-973.js | 1 +
test/compress/reduce_vars.js | 12 ++--
4 files changed, 145 insertions(+), 76 deletions(-)
diff --git a/lib/compress.js b/lib/compress.js
index ba7c10f..d848233 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -788,6 +788,14 @@ merge(Compressor.prototype, {
|| compressor.option("unsafe") && global_names(this.name);
});
+ function drop_decl(def) {
+ def._eliminiated = (def._eliminiated || 0) + 1;
+ if (def.orig.length == def._eliminiated) {
+ def.scope.functions.del(def.name);
+ def.scope.variables.del(def.name);
+ }
+ }
+
function tighten_body(statements, compressor) {
var CHANGED, max_iter = 10;
do {
@@ -1000,7 +1008,8 @@ merge(Compressor.prototype, {
function get_lhs(expr) {
if (expr instanceof AST_VarDef) {
var def = expr.name.definition();
- if (def.orig.length > 1 && !(expr.name instanceof AST_SymbolFunarg)
+ if (def.orig.length - (def._eliminiated || 0) > 1
+ && !(expr.name instanceof AST_SymbolFunarg)
|| def.references.length == 1 && !compressor.exposed(def)) {
return make_node(AST_SymbolRef, expr.name, expr.name);
}
@@ -1009,6 +1018,10 @@ merge(Compressor.prototype, {
}
}
+ function get_rvalue(expr) {
+ return expr[expr instanceof AST_Assign ? "right" : "value"];
+ }
+
function get_lvalues(expr) {
var lvalues = Object.create(null);
if (expr instanceof AST_Unary) return lvalues;
@@ -1019,7 +1032,7 @@ merge(Compressor.prototype, {
lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent());
}
});
- expr[expr instanceof AST_Assign ? "right" : "value"].walk(tw);
+ get_rvalue(expr).walk(tw);
return lvalues;
}
@@ -1043,7 +1056,9 @@ merge(Compressor.prototype, {
if (node === expr) {
found = true;
if (node instanceof AST_VarDef) {
- remove(node.name.definition().orig, node.name);
+ drop_decl(node.name.definition());
+ node.value = null;
+ return node;
}
return in_list ? MAP.skip : null;
}
@@ -1052,16 +1067,13 @@ merge(Compressor.prototype, {
case 0: return null;
case 1: return node.expressions[0];
}
- if (node instanceof AST_Definitions && node.definitions.length == 0
- || node instanceof AST_SimpleStatement && !node.body) {
- return null;
- }
+ if (node instanceof AST_SimpleStatement && !node.body) return null;
}));
}
function value_has_side_effects(expr) {
if (expr instanceof AST_Unary) return false;
- return expr[expr instanceof AST_Assign ? "right" : "value"].has_side_effects(compressor);
+ return get_rvalue(expr).has_side_effects(compressor);
}
function references_in_scope(def) {
@@ -2303,61 +2315,63 @@ merge(Compressor.prototype, {
// this scope (not in nested scopes).
var scope = this;
var tw = new TreeWalker(function(node, descend){
- if (node !== self) {
- if (node instanceof AST_Defun) {
- if (!drop_funcs && scope === self) {
- var node_def = node.name.definition();
+ if (node === self) return;
+ if (node instanceof AST_Defun) {
+ if (!drop_funcs && scope === self) {
+ var node_def = node.name.definition();
+ if (!(node_def.id in in_use_ids)) {
+ in_use_ids[node_def.id] = true;
+ in_use.push(node_def);
+ }
+ }
+ initializations.add(node.name.name, node);
+ return true; // don't go in nested scopes
+ }
+ if (node instanceof AST_SymbolFunarg && scope === self) {
+ var_defs_by_id.add(node.definition().id, node);
+ }
+ if (node instanceof AST_Definitions && scope === self) {
+ node.definitions.forEach(function(def){
+ var node_def = def.name.definition();
+ if (def.name instanceof AST_SymbolVar) {
+ var_defs_by_id.add(node_def.id, def);
+ }
+ if (!drop_vars) {
if (!(node_def.id in in_use_ids)) {
in_use_ids[node_def.id] = true;
in_use.push(node_def);
}
}
- initializations.add(node.name.name, node);
- return true; // don't go in nested scopes
- }
- if (node instanceof AST_Definitions && scope === self) {
- node.definitions.forEach(function(def){
- var node_def = def.name.definition();
- if (def.name instanceof AST_SymbolVar) {
- var_defs_by_id.add(node_def.id, def);
- }
- if (!drop_vars) {
- if (!(node_def.id in in_use_ids)) {
- in_use_ids[node_def.id] = true;
- in_use.push(node_def);
- }
+ if (def.value) {
+ initializations.add(def.name.name, def.value);
+ if (def.value.has_side_effects(compressor)) {
+ def.value.walk(tw);
}
- if (def.value) {
- initializations.add(def.name.name, def.value);
- if (def.value.has_side_effects(compressor)) {
- def.value.walk(tw);
- }
- }
- });
- return true;
- }
- var sym;
- if (scope === self
- && (sym = assign_as_unused(node)) instanceof AST_SymbolRef
- && self.variables.get(sym.name) === sym.definition()) {
- if (node instanceof AST_Assign) node.right.walk(tw);
- return true;
- }
- if (node instanceof AST_SymbolRef) {
- var node_def = node.definition();
- if (!(node_def.id in in_use_ids)) {
- in_use_ids[node_def.id] = true;
- in_use.push(node_def);
}
- return true;
- }
- if (node instanceof AST_Scope) {
- var save_scope = scope;
- scope = node;
- descend();
- scope = save_scope;
- return true;
+ });
+ return true;
+ }
+ var sym;
+ if (scope === self
+ && (sym = assign_as_unused(node)) instanceof AST_SymbolRef
+ && self.variables.get(sym.name) === sym.definition()) {
+ if (node instanceof AST_Assign) node.right.walk(tw);
+ return true;
+ }
+ if (node instanceof AST_SymbolRef) {
+ var node_def = node.definition();
+ if (!(node_def.id in in_use_ids)) {
+ in_use_ids[node_def.id] = true;
+ in_use.push(node_def);
}
+ return true;
+ }
+ if (node instanceof AST_Scope) {
+ var save_scope = scope;
+ scope = node;
+ descend();
+ scope = save_scope;
+ return true;
}
});
self.walk(tw);
@@ -2415,7 +2429,7 @@ merge(Compressor.prototype, {
var def = node.name.definition();
if (!(def.id in in_use_ids)) {
compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
- drop_decl(def, node.name);
+ drop_decl(def);
return make_node(AST_EmptyStatement, node);
}
return node;
@@ -2437,7 +2451,7 @@ merge(Compressor.prototype, {
if (var_defs.length > 1 && !def.value) {
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
remove(var_defs, def);
- drop_decl(sym, def.name);
+ drop_decl(sym);
return;
}
}
@@ -2470,7 +2484,7 @@ merge(Compressor.prototype, {
} else {
compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
}
- drop_decl(sym, def.name);
+ drop_decl(sym);
}
});
if (head.length == 0 && tail.length == 1 && tail[0].name instanceof AST_SymbolVar) {
@@ -2479,7 +2493,7 @@ merge(Compressor.prototype, {
var def = tail.pop();
compressor.warn("Converting duplicated definition of variable {name} to assignment [{file}:{line},{col}]", template(def.name));
remove(var_defs, def);
- drop_decl(def.name.definition(), def.name);
+ drop_decl(def.name.definition());
side_effects.unshift(make_node(AST_Assign, def, {
operator: "=",
left: make_node(AST_SymbolRef, def.name, def.name),
@@ -2561,14 +2575,6 @@ merge(Compressor.prototype, {
col : sym.start.col
};
}
-
- function drop_decl(def, decl) {
- remove(def.orig, decl);
- if (!def.orig.length) {
- def.scope.functions.del(def.name);
- def.scope.variables.del(def.name);
- }
- }
}
);
self.transform(tt);
@@ -3288,7 +3294,7 @@ merge(Compressor.prototype, {
}));
if (reduce_vars) name.definition().fixed = false;
}
- remove(def.name.definition().orig, def.name);
+ drop_decl(def.name.definition());
return a;
}, []);
if (assignments.length == 0) return null;
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index e2c5f1b..fe8e409 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -1388,6 +1388,7 @@ issue_1605_1: {
options = {
collapse_vars: true,
toplevel: false,
+ unused: true,
}
input: {
function foo(x) {
@@ -1410,6 +1411,7 @@ issue_1605_2: {
options = {
collapse_vars: true,
toplevel: "vars",
+ unused: true,
}
input: {
function foo(x) {
@@ -1537,6 +1539,7 @@ issue_1631_3: {
var_side_effects_1: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var print = console.log.bind(console);
@@ -1559,6 +1562,7 @@ var_side_effects_1: {
var_side_effects_2: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var print = console.log.bind(console);
@@ -1584,6 +1588,7 @@ var_side_effects_3: {
collapse_vars: true,
pure_getters: true,
unsafe: true,
+ unused: true,
}
input: {
var print = console.log.bind(console);
@@ -1659,6 +1664,7 @@ iife_2: {
}(foo);
}
expect: {
+ var foo;
!function(x) {
console.log(x);
}(bar());
@@ -1945,6 +1951,7 @@ ref_scope: {
chained_1: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var a = 2;
@@ -1961,6 +1968,7 @@ chained_1: {
chained_2: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var a;
@@ -2061,6 +2069,7 @@ inner_lvalues: {
double_def: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var a = x, a = a && y;
@@ -2075,6 +2084,7 @@ double_def: {
toplevel_single_reference: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
var a;
@@ -2084,9 +2094,10 @@ toplevel_single_reference: {
}
}
expect: {
- var a;
- for (var b in x)
+ for (var b in x) {
+ var a;
b(a = b);
+ }
}
}
@@ -2889,6 +2900,7 @@ pure_getters_chain: {
options = {
collapse_vars: true,
pure_getters: true,
+ unused: true,
}
input: {
function o(t, r) {
@@ -2909,6 +2921,7 @@ pure_getters_chain: {
conditional_1: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
function f(a, b) {
@@ -2933,6 +2946,7 @@ conditional_1: {
conditional_2: {
options = {
collapse_vars: true,
+ unused: true,
}
input: {
function f(a, b) {
@@ -3015,3 +3029,51 @@ issue_2425_3: {
}
expect_stdout: "15"
}
+
+issue_2437: {
+ options = {
+ collapse_vars: true,
+ conditionals: true,
+ inline: true,
+ join_vars: true,
+ reduce_vars: true,
+ side_effects: true,
+ sequences: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ function foo() {
+ bar();
+ }
+ function bar() {
+ if (xhrDesc) {
+ var req = new XMLHttpRequest();
+ var result = !!req.onreadystatechange;
+ Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
+ return result;
+ }
+ else {
+ var req = new XMLHttpRequest();
+ var detectFunc = function () { };
+ req.onreadystatechange = detectFunc;
+ var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
+ req.onreadystatechange = null;
+ return result;
+ }
+ }
+ foo();
+ }
+ expect: {
+ !function() {
+ if (xhrDesc)
+ return result = !!(req = new XMLHttpRequest()).onreadystatechange,
+ Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
+ result;
+ var req = new XMLHttpRequest(), detectFunc = function() {};
+ req.onreadystatechange = detectFunc;
+ var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
+ req.onreadystatechange = null;
+ }();
+ }
+}
diff --git a/test/compress/issue-973.js b/test/compress/issue-973.js
index 30f886a..fee05df 100644
--- a/test/compress/issue-973.js
+++ b/test/compress/issue-973.js
@@ -51,6 +51,7 @@ this_binding_collapse_vars: {
options = {
collapse_vars: true,
toplevel: true,
+ unused: true,
};
input: {
var c = a; c();
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 7714ad5..1acd902 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -2131,14 +2131,13 @@ redefine_farg_1: {
}
expect: {
function f(a) {
- var a;
return typeof a;
}
function g() {
- return"number";
+ return "number";
}
function h(a, b) {
- var a = b;
+ a = b;
return typeof a;
}
console.log(f([]), g([]), h([]));
@@ -2173,10 +2172,9 @@ redefine_farg_2: {
}
expect: {
console.log(function(a) {
- var a;
return typeof a;
}([]), "number",function(a, b) {
- var a = b;
+ a = b;
return typeof a;
}([]));
}
@@ -2185,11 +2183,13 @@ redefine_farg_2: {
redefine_farg_3: {
options = {
+ cascade: true,
evaluate: true,
inline: true,
keep_fargs: false,
- passes: 3,
+ passes: 2,
reduce_vars: true,
+ sequences: true,
side_effects: true,
toplevel: true,
unused: true,
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git
More information about the Pkg-javascript-commits
mailing list