diff options
Diffstat (limited to 'node_modules/terser/lib/compress/drop-unused.js')
| -rw-r--r-- | node_modules/terser/lib/compress/drop-unused.js | 544 |
1 files changed, 0 insertions, 544 deletions
diff --git a/node_modules/terser/lib/compress/drop-unused.js b/node_modules/terser/lib/compress/drop-unused.js deleted file mode 100644 index 9d9555da..00000000 --- a/node_modules/terser/lib/compress/drop-unused.js +++ /dev/null @@ -1,544 +0,0 @@ -/*********************************************************************** - - A JavaScript tokenizer / parser / beautifier / compressor. - https://github.com/mishoo/UglifyJS2 - - -------------------------------- (C) --------------------------------- - - Author: Mihai Bazon - <mihai.bazon@gmail.com> - http://mihai.bazon.net/blog - - Distributed under the BSD license: - - Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - ***********************************************************************/ - -import { - AST_Accessor, - AST_Assign, - AST_BlockStatement, - AST_Call, - AST_Class, - AST_ClassExpression, - AST_ClassStaticBlock, - AST_DefaultAssign, - AST_DefClass, - AST_Definitions, - AST_Defun, - AST_Destructuring, - AST_EmptyStatement, - AST_Expansion, - AST_Export, - AST_For, - AST_ForIn, - AST_Function, - AST_LabeledStatement, - AST_Lambda, - AST_Number, - AST_Scope, - AST_Sequence, - AST_SimpleStatement, - AST_SymbolBlockDeclaration, - AST_SymbolCatch, - AST_SymbolDeclaration, - AST_SymbolFunarg, - AST_SymbolRef, - AST_SymbolVar, - AST_Toplevel, - AST_Unary, - AST_Var, - - TreeTransformer, - TreeWalker, - walk, -} from "../ast.js"; -import { - keep_name, - make_node, - map_add, - MAP, - remove, - return_false, -} from "../utils/index.js"; -import { SymbolDef } from "../scope.js"; - -import { - WRITE_ONLY, - UNUSED, - - has_flag, - set_flag, -} from "./compressor-flags.js"; -import { - make_sequence, - maintain_this_binding, - is_empty, - is_ref_of, - can_be_evicted_from_block, - requires_sequence_to_maintain_binding, -} from "./common.js"; - -const r_keep_assign = /keep_assign/; - -/** Drop unused variables from this scope */ -AST_Scope.DEFMETHOD("drop_unused", function(compressor) { - if (!compressor.option("unused")) return; - if (compressor.has_directive("use asm")) return; - if (!this.variables) return; // not really a scope (eg: AST_Class) - - var self = this; - if (self.pinned()) return; - var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs; - var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars; - const assign_as_unused = r_keep_assign.test(compressor.option("unused")) ? return_false : function(node) { - if (node instanceof AST_Assign - && !node.logical - && (has_flag(node, WRITE_ONLY) || node.operator == "=") - ) { - return node.left; - } - if (node instanceof AST_Unary && has_flag(node, WRITE_ONLY)) { - return node.expression; - } - }; - var in_use_ids = new Map(); - var fixed_ids = new Map(); - if (self instanceof AST_Toplevel && compressor.top_retain) { - self.variables.forEach(function(def) { - if (compressor.top_retain(def)) { - in_use_ids.set(def.id, def); - } - }); - } - var var_defs_by_id = new Map(); - var initializations = new Map(); - - // pass 1: find out which symbols are directly used in - // this scope (not in nested scopes). - var scope = this; - var tw = new TreeWalker(function(node, descend) { - if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive("use strict")) { - node.argnames.forEach(function(argname) { - if (!(argname instanceof AST_SymbolDeclaration)) return; - var def = argname.definition(); - in_use_ids.set(def.id, def); - }); - } - if (node === self) return; - if (node instanceof AST_Class && node.has_side_effects(compressor)) { - if (node.is_self_referential()) { - descend(); - } else { - node.visit_nondeferred_class_parts(tw); - } - } - if (node instanceof AST_Defun || node instanceof AST_DefClass) { - var node_def = node.name.definition(); - const in_export = tw.parent() instanceof AST_Export; - if (in_export || !drop_funcs && scope === self) { - if (node_def.global) { - in_use_ids.set(node_def.id, node_def); - } - } - - map_add(initializations, node_def.id, node); - return true; // don't go in nested scopes - } - // In the root scope, we drop things. In inner scopes, we just check for uses. - const in_root_scope = scope === self; - if (node instanceof AST_SymbolFunarg && in_root_scope) { - map_add(var_defs_by_id, node.definition().id, node); - } - if (node instanceof AST_Definitions && in_root_scope) { - const in_export = tw.parent() instanceof AST_Export; - node.definitions.forEach(function(def) { - if (def.name instanceof AST_SymbolVar) { - map_add(var_defs_by_id, def.name.definition().id, def); - } - if (in_export || !drop_vars) { - walk(def.name, node => { - if (node instanceof AST_SymbolDeclaration) { - const def = node.definition(); - if (def.global) { - in_use_ids.set(def.id, def); - } - } - }); - } - if (def.name instanceof AST_Destructuring) { - def.walk(tw); - } - if (def.name instanceof AST_SymbolDeclaration && def.value) { - var node_def = def.name.definition(); - map_add(initializations, node_def.id, def.value); - if (!node_def.chained && def.name.fixed_value() === def.value) { - fixed_ids.set(node_def.id, def); - } - if (def.value.has_side_effects(compressor)) { - def.value.walk(tw); - } - } - }); - return true; - } - return scan_ref_scoped(node, descend); - }); - self.walk(tw); - // pass 2: for every used symbol we need to walk its - // initialization code to figure out if it uses other - // symbols (that may not be in_use). - tw = new TreeWalker(scan_ref_scoped); - in_use_ids.forEach(function (def) { - var init = initializations.get(def.id); - if (init) init.forEach(function(init) { - init.walk(tw); - }); - }); - // pass 3: we should drop declarations not in_use - var tt = new TreeTransformer( - function before(node, descend, in_list) { - var parent = tt.parent(); - if (drop_vars) { - const sym = assign_as_unused(node); - if (sym instanceof AST_SymbolRef) { - var def = sym.definition(); - var in_use = in_use_ids.has(def.id); - if (node instanceof AST_Assign) { - if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) { - const assignee = node.right.transform(tt); - if (!in_use && !assignee.has_side_effects(compressor) && !is_used_in_expression(tt)) { - return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 }); - } - return maintain_this_binding(parent, node, assignee); - } - } else if (!in_use) { - return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 }); - } - } - } - if (scope !== self) return; - var def; - if (node.name - && (node instanceof AST_ClassExpression - && !keep_name(compressor.option("keep_classnames"), (def = node.name.definition()).name) - || node instanceof AST_Function - && !keep_name(compressor.option("keep_fnames"), (def = node.name.definition()).name))) { - // any declarations with same name will overshadow - // name of this anonymous function and can therefore - // never be used anywhere - if (!in_use_ids.has(def.id) || def.orig.length > 1) node.name = null; - } - if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { - var trim = - !compressor.option("keep_fargs") - // Is this an IIFE that won't refer to its name? - || parent instanceof AST_Call - && parent.expression === node - && !node.pinned() - && (!node.name || node.name.unreferenced()); - for (var a = node.argnames, i = a.length; --i >= 0;) { - var sym = a[i]; - if (sym instanceof AST_Expansion) { - sym = sym.expression; - } - if (sym instanceof AST_DefaultAssign) { - sym = sym.left; - } - // Do not drop destructuring arguments. - // They constitute a type assertion of sorts - if ( - !(sym instanceof AST_Destructuring) - && !in_use_ids.has(sym.definition().id) - ) { - set_flag(sym, UNUSED); - if (trim) { - a.pop(); - } - } else { - trim = false; - } - } - } - if (node instanceof AST_DefClass && node !== self) { - const def = node.name.definition(); - descend(node, this); - const keep_class = def.global && !drop_funcs || in_use_ids.has(def.id); - if (!keep_class) { - const kept = node.drop_side_effect_free(compressor); - if (kept == null) { - def.eliminated++; - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); - } - return kept; - } - return node; - } - if (node instanceof AST_Defun && node !== self) { - const def = node.name.definition(); - const keep = def.global && !drop_funcs || in_use_ids.has(def.id); - if (!keep) { - def.eliminated++; - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); - } - } - if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) { - var drop_block = !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var); - // place uninitialized names at the start - var body = [], head = [], tail = []; - // for unused names whose initialization has - // side effects, we can cascade the init. code - // into the next one, or next statement. - var side_effects = []; - node.definitions.forEach(function(def) { - if (def.value) def.value = def.value.transform(tt); - var is_destructure = def.name instanceof AST_Destructuring; - var sym = is_destructure - ? new SymbolDef(null, { name: "<destructure>" }) /* fake SymbolDef */ - : def.name.definition(); - if (drop_block && sym.global) return tail.push(def); - if (!(drop_vars || drop_block) - || is_destructure - && (def.name.names.length - || def.name.is_array - || compressor.option("pure_getters") != true) - || in_use_ids.has(sym.id) - ) { - if (def.value && fixed_ids.has(sym.id) && fixed_ids.get(sym.id) !== def) { - def.value = def.value.drop_side_effect_free(compressor); - } - if (def.name instanceof AST_SymbolVar) { - var var_defs = var_defs_by_id.get(sym.id); - if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) { - if (def.value) { - var ref = make_node(AST_SymbolRef, def.name, def.name); - sym.references.push(ref); - var assign = make_node(AST_Assign, def, { - operator: "=", - logical: false, - left: ref, - right: def.value - }); - if (fixed_ids.get(sym.id) === def) { - fixed_ids.set(sym.id, assign); - } - side_effects.push(assign.transform(tt)); - } - remove(var_defs, def); - sym.eliminated++; - return; - } - } - if (def.value) { - if (side_effects.length > 0) { - if (tail.length > 0) { - side_effects.push(def.value); - def.value = make_sequence(def.value, side_effects); - } else { - body.push(make_node(AST_SimpleStatement, node, { - body: make_sequence(node, side_effects) - })); - } - side_effects = []; - } - tail.push(def); - } else { - head.push(def); - } - } else if (sym.orig[0] instanceof AST_SymbolCatch) { - var value = def.value && def.value.drop_side_effect_free(compressor); - if (value) side_effects.push(value); - def.value = null; - head.push(def); - } else { - var value = def.value && def.value.drop_side_effect_free(compressor); - if (value) { - side_effects.push(value); - } - sym.eliminated++; - } - }); - if (head.length > 0 || tail.length > 0) { - node.definitions = head.concat(tail); - body.push(node); - } - if (side_effects.length > 0) { - body.push(make_node(AST_SimpleStatement, node, { - body: make_sequence(node, side_effects) - })); - } - switch (body.length) { - case 0: - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); - case 1: - return body[0]; - default: - return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { body }); - } - } - // certain combination of unused name + side effect leads to: - // https://github.com/mishoo/UglifyJS2/issues/44 - // https://github.com/mishoo/UglifyJS2/issues/1830 - // https://github.com/mishoo/UglifyJS2/issues/1838 - // that's an invalid AST. - // We fix it at this stage by moving the `var` outside the `for`. - if (node instanceof AST_For) { - descend(node, this); - var block; - if (node.init instanceof AST_BlockStatement) { - block = node.init; - node.init = block.body.pop(); - block.body.push(node); - } - if (node.init instanceof AST_SimpleStatement) { - node.init = node.init.body; - } else if (is_empty(node.init)) { - node.init = null; - } - return !block ? node : in_list ? MAP.splice(block.body) : block; - } - if (node instanceof AST_LabeledStatement - && node.body instanceof AST_For - ) { - descend(node, this); - if (node.body instanceof AST_BlockStatement) { - var block = node.body; - node.body = block.body.pop(); - block.body.push(node); - return in_list ? MAP.splice(block.body) : block; - } - return node; - } - if (node instanceof AST_BlockStatement) { - descend(node, this); - if (in_list && node.body.every(can_be_evicted_from_block)) { - return MAP.splice(node.body); - } - return node; - } - if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) { - const save_scope = scope; - scope = node; - descend(node, this); - scope = save_scope; - return node; - } - }, - function after(node, in_list) { - if (node instanceof AST_Sequence) { - switch (node.expressions.length) { - case 0: return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 }); - case 1: return node.expressions[0]; - } - } - } - ); - - self.transform(tt); - - function scan_ref_scoped(node, descend) { - var node_def; - const sym = assign_as_unused(node); - if (sym instanceof AST_SymbolRef - && !is_ref_of(node.left, AST_SymbolBlockDeclaration) - && self.variables.get(sym.name) === (node_def = sym.definition()) - ) { - if (node instanceof AST_Assign) { - node.right.walk(tw); - if (!node_def.chained && node.left.fixed_value() === node.right) { - fixed_ids.set(node_def.id, node); - } - } - return true; - } - if (node instanceof AST_SymbolRef) { - node_def = node.definition(); - if (!in_use_ids.has(node_def.id)) { - in_use_ids.set(node_def.id, node_def); - if (node_def.orig[0] instanceof AST_SymbolCatch) { - const redef = node_def.scope.is_block_scope() - && node_def.scope.get_defun_scope().variables.get(node_def.name); - if (redef) in_use_ids.set(redef.id, redef); - } - } - return true; - } - if (node instanceof AST_Class) { - descend(); - return true; - } - if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) { - var save_scope = scope; - scope = node; - descend(); - scope = save_scope; - return true; - } - } -}); - -/** - * Check if a node may be used by the expression it's in - * void (0, 1, {node}, 2) -> false - * console.log(0, {node}) -> true - */ -function is_used_in_expression(tw) { - for (let p = -1, node, parent; node = tw.parent(p), parent = tw.parent(p + 1); p++) { - if (parent instanceof AST_Sequence) { - const nth_expression = parent.expressions.indexOf(node); - if (nth_expression !== parent.expressions.length - 1) { - // Detect (0, x.noThis)() constructs - const grandparent = tw.parent(p + 2); - if ( - parent.expressions.length > 2 - || parent.expressions.length === 1 - || !requires_sequence_to_maintain_binding(grandparent, parent, parent.expressions[1]) - ) { - return false; - } - return true; - } else { - continue; - } - } - if (parent instanceof AST_Unary) { - const op = parent.operator; - if (op === "void") { - return false; - } - if (op === "typeof" || op === "+" || op === "-" || op === "!" || op === "~") { - continue; - } - } - return true; - } - - return true; -} |
