From 1dd339f95e1037e8ff77cfb8fb213b920ea87ef4 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 14 Mar 2017 13:13:43 +0800 Subject: [PATCH] fix `unused` crashes (#1599) - `AST_DefaultAssign` on `keep_fargs` - `AST_Expansion on` `keep_fargs` - `AST_Destructuring` on top-level declarations without `toplevel` --- lib/ast.js | 3 --- lib/compress.js | 27 +++++++++++++++++---------- test/compress/destructuring.js | 14 ++++++++++++++ test/compress/harmony.js | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index 2f598956..428dbeaa 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -814,9 +814,6 @@ var AST_VarDef = DEFNODE("VarDef", "name value", { name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable", value: "[AST_Node?] initializer, or null of there's no initializer" }, - is_destructuring: function() { - return this.name instanceof AST_Destructuring; - }, _walk: function(visitor) { return visitor._visit(this, function(){ this.name._walk(visitor); diff --git a/lib/compress.js b/lib/compress.js index 6dd7e562..25a7a3bb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1789,14 +1789,18 @@ merge(Compressor.prototype, { if (node instanceof AST_Definitions && scope === self) { node.definitions.forEach(function(def){ if (!drop_vars) { - var node_def = def.name.definition(); - if (node_def.global && !(node_def.id in in_use_ids)) { - in_use_ids[node_def.id] = true; - in_use.push(node_def); - } + def.name.walk(new TreeWalker(function(node) { + if (node instanceof AST_SymbolDeclaration) { + var def = node.definition(); + if (def.global && !(def.id in in_use_ids)) { + in_use_ids[def.id] = true; + in_use.push(def); + } + } + })); } if (def.value) { - if (def.is_destructuring()) { + if (def.name instanceof AST_Destructuring) { var destructuring_cache = destructuring_value; destructuring_value = def.value; in_definition = true; @@ -1907,7 +1911,10 @@ merge(Compressor.prototype, { for (var a = node.argnames, i = a.length; --i >= 0;) { var sym = a[i]; if (sym instanceof AST_Expansion) { - sym = sym.symbol; + sym = sym.expression; + } + if (sym instanceof AST_DefaultAssign) { + sym = sym.left; } // Do not drop destructuring arguments. // They constitute a type assertion, so dropping @@ -1947,7 +1954,7 @@ merge(Compressor.prototype, { if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { var def = node.definitions.filter(function(def){ if (def.value) def.value = def.value.transform(tt); - if (def.is_destructuring()) return true; + if (def.name instanceof AST_Destructuring) return true; if (def.name.definition().id in in_use_ids) return true; if (!drop_vars && def.name.definition().global) return true; @@ -2090,7 +2097,7 @@ merge(Compressor.prototype, { } if (node instanceof AST_Var && hoist_vars) { node.definitions.forEach(function(def){ - if (def.is_destructuring()) { return; } + if (def.name instanceof AST_Destructuring) return; vars.set(def.name.name, def); ++vars_found; }); @@ -2698,7 +2705,7 @@ merge(Compressor.prototype, { AST_Definitions.DEFMETHOD("to_assignments", function(){ var assignments = this.definitions.reduce(function(a, def){ - if (def.value && !def.is_destructuring()) { + if (def.value && !(def.name instanceof AST_Destructuring)) { var name = make_node(AST_SymbolRef, def.name, def.name); a.push(make_node(AST_Assign, def, { operator : "=", diff --git a/test/compress/destructuring.js b/test/compress/destructuring.js index 9e4a0988..313d47d7 100644 --- a/test/compress/destructuring.js +++ b/test/compress/destructuring.js @@ -293,3 +293,17 @@ reduce_vars: { for ([x,y] in pairs); } } + +unused: { + options = { + unused: true, + } + input: { + let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 }; + console.log(a); + } + expect: { + let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 }; + console.log(a); + } +} diff --git a/test/compress/harmony.js b/test/compress/harmony.js index 29c7d609..9f13537c 100644 --- a/test/compress/harmony.js +++ b/test/compress/harmony.js @@ -286,3 +286,37 @@ fat_arrow_as_param: { } expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));" } + +default_assign: { + options = { + keep_fargs: false, + unused: true, + } + input: { + function f(a, b = 3) { + console.log(a); + } + } + expect: { + function f(a) { + console.log(a); + } + } +} + +expansion: { + options = { + keep_fargs: false, + unused: true, + } + input: { + function f(a, ...b) { + console.log(a); + } + } + expect: { + function f(a) { + console.log(a); + } + } +}