diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-04-18 13:38:42 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-18 13:38:42 +0800 |
commit | 5d9f1da3abc58bce95dd240bd586bedb4eb04771 (patch) | |
tree | d9a2ef3198cf398c04a44d52cd74285cfb97fc1b /lib/compress.js | |
parent | d1aa09c5c7af14bf5f17cc7ea2ab5d6be20e3220 (diff) | |
download | tracifyjs-5d9f1da3abc58bce95dd240bd586bedb4eb04771.tar.gz tracifyjs-5d9f1da3abc58bce95dd240bd586bedb4eb04771.zip |
support safe reassignments in `reduce_vars` (#1823)
`var a=1;a=2;x(a)` => `x(2)`
fix pre-existing issues
- reference counting on assignment
- walking of anonymous functions
- chained assignment
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/lib/compress.js b/lib/compress.js index 0dfe2a3c..596b03fa 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -267,7 +267,7 @@ merge(Compressor.prototype, { if (node instanceof AST_SymbolRef) { var d = node.definition(); d.references.push(node); - if (d.fixed === undefined || !is_safe(d) + if (d.fixed === undefined || !safe_to_read(d) || is_modified(node, 0, is_immutable(node.fixed_value()))) { d.fixed = false; } @@ -277,7 +277,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_VarDef) { var d = node.name.definition(); - if (d.fixed == null) { + if (d.fixed === undefined || safe_to_assign(d, node.value)) { if (node.value) { d.fixed = function() { return node.value; @@ -297,7 +297,8 @@ merge(Compressor.prototype, { && node.operator == "=" && node.left instanceof AST_SymbolRef) { var d = node.left.definition(); - if (HOP(safe_ids, d.id) && d.fixed == null) { + if (safe_to_assign(d, node.right)) { + d.references.push(node.left); d.fixed = function() { return node.right; }; @@ -309,7 +310,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_Defun) { var d = node.name.definition(); - if (!toplevel && d.global || is_safe(d)) { + if (!toplevel && d.global || safe_to_read(d)) { d.fixed = false; } else { d.fixed = node; @@ -321,13 +322,12 @@ merge(Compressor.prototype, { safe_ids = save_ids; return true; } - var iife; - if (node instanceof AST_Function - && (iife = tw.parent()) instanceof AST_Call - && iife.expression === node) { - if (node.name) { - node.name.definition().fixed = node; - } else { + if (node instanceof AST_Function) { + push(); + var iife; + if (!node.name + && (iife = tw.parent()) instanceof AST_Call + && iife.expression === node) { // Virtually turn IIFE parameters into variable definitions: // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})() // So existing transformation rules can work on them. @@ -339,6 +339,9 @@ merge(Compressor.prototype, { mark(d, true); }); } + descend(); + pop(); + return true; } if (node instanceof AST_Binary && (node.operator == "&&" || node.operator == "||")) { @@ -385,11 +388,19 @@ merge(Compressor.prototype, { } if (node instanceof AST_For) { if (node.init) node.init.walk(tw); + if (node.condition) { + push(); + node.condition.walk(tw); + pop(); + } push(); - if (node.condition) node.condition.walk(tw); node.body.walk(tw); - if (node.step) node.step.walk(tw); pop(); + if (node.step) { + push(); + node.step.walk(tw); + pop(); + } return true; } if (node instanceof AST_ForIn) { @@ -426,7 +437,7 @@ merge(Compressor.prototype, { safe_ids[def.id] = safe; } - function is_safe(def) { + function safe_to_read(def) { if (safe_ids[def.id]) { if (def.fixed == null) { var orig = def.orig[0]; @@ -437,6 +448,18 @@ merge(Compressor.prototype, { } } + function safe_to_assign(def, value) { + if (!HOP(safe_ids, def.id)) return false; + if (!safe_to_read(def)) return false; + if (def.fixed === false) return false; + if (def.fixed != null && (!value || def.references.length > 0)) return false; + return !def.orig.some(function(sym) { + return sym instanceof AST_SymbolConst + || sym instanceof AST_SymbolDefun + || sym instanceof AST_SymbolLambda; + }); + } + function push() { safe_ids = Object.create(safe_ids); } |