| 
							
								 | 
							
							/***********************************************************************
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							  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_Array,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Arrow,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Assign,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_BigInt,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Binary,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Block,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_BlockStatement,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Boolean,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Break,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Call,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Catch,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Chain,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Class,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ClassProperty,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ClassStaticBlock,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ConciseMethod,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Conditional,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Const,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Constant,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Debugger,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_DefaultAssign,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Definitions,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Defun,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Destructuring,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Directive,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Do,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Dot,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_DWLoop,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_EmptyStatement,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Exit,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Expansion,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Export,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_False,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_For,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ForIn,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Function,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Hole,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_If,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Import,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Infinity,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_LabeledStatement,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Lambda,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Let,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_NaN,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_New,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Node,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Null,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Number,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Object,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ObjectKeyVal,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_ObjectProperty,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_PrefixedTemplateString,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_PropAccess,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_RegExp,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Return,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Scope,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Sequence,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SimpleStatement,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Statement,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_String,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Sub,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Switch,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SwitchBranch,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Symbol,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolClassProperty,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolDeclaration,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolDefun,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolExport,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolFunarg,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolLambda,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolLet,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolMethod,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_SymbolRef,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_TemplateString,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_This,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Toplevel,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_True,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Try,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Unary,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_UnaryPostfix,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_UnaryPrefix,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Undefined,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Var,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_VarDef,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_While,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_With,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    AST_Yield,
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    TreeTransformer,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    TreeWalker,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    walk,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    walk_abort,
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    _INLINE,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    _NOINLINE,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    _PURE
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "../ast.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    defaults,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    HOP,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    make_node,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    makePredicate,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    MAP,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    remove,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return_false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return_true,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    regexp_source_fix,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    has_annotation,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    regexp_is_safe,
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "../utils/index.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { first_in_statement } from "../utils/first_in_statement.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { equivalent_to } from "../equivalent-to.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_basic_identifier_string,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    JS_Parse_Error,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    parse,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    PRECEDENCE,
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "../parse.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { OutputStream } from "../output.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { base54, format_mangler_options } from "../scope.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import "../size.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							import "./evaluate.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import "./drop-side-effect-free.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import "./drop-unused.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import "./reduce-vars.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_undeclared_ref,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lazy_op,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_nullish,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_undefined,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_lhs,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    aborts,
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "./inference.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    SQUEEZED,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    OPTIMIZED,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    CLEAR_BETWEEN_PASSES,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    TOP,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    UNDEFINED,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    UNUSED,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    TRUTHY,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    FALSY,
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    has_flag,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    set_flag,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    clear_flag,
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "./compressor-flags.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    make_sequence,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    best_of,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    best_of_expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    make_node_from_constant,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    merge_sequence,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    get_simple_key,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    has_break_or_continue,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    maintain_this_binding,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_empty,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_identifier_atom,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_reachable,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    can_be_evicted_from_block,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    as_statement_array,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    retain_top_func,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    is_func_expr,
 | 
						
						
						
						
							 | 
							
								 | 
							
							} from "./common.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { tighten_body, trim_unreachable_code } from "./tighten-body.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							import { inline_into_symbolref, inline_into_call } from "./inline.js";
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							class Compressor extends TreeWalker {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    constructor(options, { false_by_default = false, mangle_options = false }) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        super();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (options.defaults !== undefined && !options.defaults) false_by_default = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this.options = defaults(options, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            arguments     : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            arrows        : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            booleans      : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            booleans_as_integers : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            collapse_vars : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            comparisons   : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            computed_props: !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            conditionals  : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            dead_code     : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            defaults      : true,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            directives    : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            drop_console  : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            drop_debugger : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ecma          : 5,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            evaluate      : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expression    : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            global_defs   : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            hoist_funs    : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            hoist_props   : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            hoist_vars    : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ie8           : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if_return     : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            inline        : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            join_vars     : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            keep_classnames: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            keep_fargs    : true,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            keep_fnames   : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            keep_infinity : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            loops         : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            module        : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            negate_iife   : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            passes        : 1,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            properties    : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            pure_getters  : !false_by_default && "strict",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            pure_funcs    : null,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            reduce_funcs  : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            reduce_vars   : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            sequences     : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            side_effects  : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            switches      : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            top_retain    : null,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            toplevel      : !!(options && options["top_retain"]),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            typeofs       : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe        : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_arrows : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_comps  : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_Function: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_math   : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_symbols: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_methods: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_proto  : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_regexp : false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unsafe_undefined: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            unused        : !false_by_default,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            warnings      : false  // legacy
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }, true);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var global_defs = this.options["global_defs"];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (typeof global_defs == "object") for (var key in global_defs) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (key[0] === "@" && HOP(global_defs, key)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                global_defs[key.slice(1)] = parse(global_defs[key], {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: true
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.options["inline"] === true) this.options["inline"] = 3;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var pure_funcs = this.options["pure_funcs"];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (typeof pure_funcs == "function") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.pure_funcs = pure_funcs;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.pure_funcs = pure_funcs ? function(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return !pure_funcs.includes(node.expression.print_to_string());
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } : return_true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var top_retain = this.options["top_retain"];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (top_retain instanceof RegExp) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.top_retain = function(def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return top_retain.test(def.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            };
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (typeof top_retain == "function") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.top_retain = top_retain;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (top_retain) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (typeof top_retain == "string") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                top_retain = top_retain.split(/,/);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.top_retain = function(def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return top_retain.includes(def.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            };
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.options["module"]) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.directives["use strict"] = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this.options["toplevel"] = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var toplevel = this.options["toplevel"];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this.toplevel = typeof toplevel == "string" ? {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            funcs: /funcs/.test(toplevel),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vars: /vars/.test(toplevel)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } : {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            funcs: toplevel,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vars: toplevel
 | 
						
						
						
						
							 | 
							
								 | 
							
							        };
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var sequences = this.options["sequences"];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this.sequences_limit = sequences == 1 ? 800 : sequences | 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this.evaluated_regexps = new Map();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this._toplevel = undefined;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this.mangle_options = mangle_options
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ? format_mangler_options(mangle_options)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            : mangle_options;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    option(key) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return this.options[key];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    exposed(def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (def.export) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (def.global) for (var i = 0, len = def.orig.length; i < len; i++)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"])
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    in_boolean_context() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!this.option("booleans")) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var self = this.self();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var i = 0, p; p = this.parent(i); i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (p instanceof AST_SimpleStatement
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_Conditional && p.condition === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_DWLoop && p.condition === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_For && p.condition === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_If && p.condition === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                p instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        p.operator == "&&"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        || p.operator == "||"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        || p.operator == "??"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    )
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p instanceof AST_Conditional
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || p.tail_node() === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self = p;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    get_toplevel() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return this._toplevel;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    compress(toplevel) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        toplevel = toplevel.resolve_defines(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this._toplevel = toplevel;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.option("expression")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this._toplevel.process_expression(true);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var passes = +this.options.passes || 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var min_count = 1 / 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var stopping = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var nth_identifier = this.mangle_options && this.mangle_options.nth_identifier || base54;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var mangle = { ie8: this.option("ie8"), nth_identifier: nth_identifier };
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var pass = 0; pass < passes; pass++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this._toplevel.figure_out_scope(mangle);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (pass === 0 && this.option("drop_console")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // must be run before reduce_vars and compress pass
 | 
						
						
						
						
							 | 
							
								 | 
							
							                this._toplevel = this._toplevel.drop_console();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (pass > 0 || this.option("reduce_vars")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                this._toplevel.reset_opt_flags(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this._toplevel = this._toplevel.transform(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (passes > 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                let count = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                walk(this._toplevel, () => { count++; });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (count < min_count) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    min_count = count;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    stopping = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else if (stopping) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    stopping = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.option("expression")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            this._toplevel.process_expression(false);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        toplevel = this._toplevel;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        this._toplevel = undefined;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return toplevel;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    before(node, descend) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (has_flag(node, SQUEEZED)) return node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var was_scope = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node instanceof AST_Scope) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node = node.hoist_properties(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node = node.hoist_declarations(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            was_scope = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // Before https://github.com/mishoo/UglifyJS2/pull/1602 AST_Node.optimize()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // would call AST_Node.transform() if a different instance of AST_Node is
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // produced after def_optimize().
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // This corrupts TreeWalker.stack, which cause AST look-ups to malfunction.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // Migrate and defer all children's AST_Node.transform() to below, which
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // will now happen after this parent AST_Node has been properly substituted
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // thus gives a consistent AST snapshot.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        descend(node, this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // Existing code relies on how AST_Node.optimize() worked, and omitting the
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // following replacement call would result in degraded efficiency of both
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // output and performance.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        descend(node, this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var opt = node.optimize(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (was_scope && opt instanceof AST_Scope) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            opt.drop_unused(this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            descend(opt, this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (opt === node) set_flag(opt, SQUEEZED);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return opt;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function def_optimize(node, optimizer) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    node.DEFMETHOD("optimize", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var self = this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (has_flag(self, OPTIMIZED)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (compressor.has_directive("use asm")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var opt = optimizer(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        set_flag(opt, OPTIMIZED);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return opt;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Node, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Toplevel.DEFMETHOD("drop_console", function() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return this.transform(new TreeTransformer(function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.TYPE == "Call") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var exp = self.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (exp instanceof AST_PropAccess) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var name = exp.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                while (name.expression) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    name = name.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (is_undeclared_ref(name) && name.name == "console") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return make_node(AST_Undefined, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Node.DEFMETHOD("equivalent_to", function(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return equivalent_to(this, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Scope.DEFMETHOD("process_expression", function(insert, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var self = this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var tt = new TreeTransformer(function(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (insert && node instanceof AST_SimpleStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Return, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: node.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!insert && node instanceof AST_Return) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var value = node.value && node.value.drop_side_effect_free(compressor, true);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return value
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ? make_node(AST_SimpleStatement, node, { body: value })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    : make_node(AST_EmptyStatement, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_SimpleStatement, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: node.value || make_node(AST_UnaryPrefix, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "void",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: make_node(AST_Number, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node instanceof AST_Class || node instanceof AST_Lambda && node !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node instanceof AST_Block) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var index = node.body.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (index >= 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                node.body[index] = node.body[index].transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (node instanceof AST_If) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node.body = node.body.transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node.alternative) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                node.alternative = node.alternative.transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (node instanceof AST_With) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node.body = node.body.transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self.transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const self = this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const reduce_vars = compressor.option("reduce_vars");
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const preparation = new TreeWalker(function(node, descend) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        clear_flag(node, CLEAR_BETWEEN_PASSES);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (reduce_vars) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (compressor.top_retain
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node instanceof AST_Defun  // Only functions are retained
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && preparation.parent() === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                set_flag(node, TOP);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return node.reduce_vars(preparation, descend, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // Stack of look-up tables to keep track of whether a `SymbolDef` has been
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // properly assigned before use:
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // - `push()` & `pop()` when visiting conditional branches
 | 
						
						
						
						
							 | 
							
								 | 
							
							    preparation.safe_ids = Object.create(null);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    preparation.in_loop = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    preparation.loop_ids = new Map();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    preparation.defs_to_safe_ids = new Map();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self.walk(preparation);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Symbol.DEFMETHOD("fixed_value", function() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var fixed = this.thedef.fixed;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!fixed || fixed instanceof AST_Node) return fixed;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return fixed();
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_SymbolRef.DEFMETHOD("is_immutable", function() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var orig = this.definition().orig;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return orig.length == 1 && orig[0] instanceof AST_SymbolLambda;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function find_variable(compressor, name) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var scope, i = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    while (scope = compressor.parent(i++)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (scope instanceof AST_Scope) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (scope instanceof AST_Catch && scope.argname) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            scope = scope.argname.definition().scope;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return scope.find_variable(name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError");
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return !this.definition().undeclared
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || compressor.option("unsafe") && global_names.has(this.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							/* -----[ optimizers ]----- */
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							var directives = new Set(["use asm", "use strict"]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Directive, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("directives")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (!directives.has(self.value) || compressor.has_directive(self.value) !== self)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Debugger, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("drop_debugger"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_LabeledStatement, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.body instanceof AST_Break
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && compressor.loopcontrol_target(self.body) === self.body) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self.label.references.length == 0 ? self.body : self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Block, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tighten_body(self.body, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function can_be_extracted_from_if_block(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return !(
 | 
						
						
						
						
							 | 
							
								 | 
							
							        node instanceof AST_Const
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || node instanceof AST_Let
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || node instanceof AST_Class
 | 
						
						
						
						
							 | 
							
								 | 
							
							    );
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_BlockStatement, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tighten_body(self.body, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    switch (self.body.length) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case 1:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!compressor.has_directive("use strict")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && compressor.parent() instanceof AST_If
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && can_be_extracted_from_if_block(self.body[0])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || can_be_evicted_from_block(self.body[0])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.body[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case 0: return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function opt_AST_Lambda(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tighten_body(self.body, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("side_effects")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.body.length == 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.body[0] === compressor.has_directive("use strict")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.body.length = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Lambda, opt_AST_Lambda);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var self = this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.has_directive("use asm")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // Hoisting makes no sense in an arrow func
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!Array.isArray(self.body)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var hoist_funs = compressor.option("hoist_funs");
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var hoist_vars = compressor.option("hoist_vars");
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (hoist_funs || hoist_vars) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var dirs = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var hoisted = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var vars = new Map(), vars_found = 0, var_decl = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // let's count var_decl first, we seem to waste a lot of
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // space if we hoist `var` when there's only one.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        walk(self, node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node instanceof AST_Scope && node !== self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node instanceof AST_Var) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ++var_decl;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        hoist_vars = hoist_vars && var_decl > 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var tt = new TreeTransformer(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            function before(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (node !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (node instanceof AST_Directive) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        dirs.push(node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return make_node(AST_EmptyStatement, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (hoist_funs && node instanceof AST_Defun
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        && !(tt.parent() instanceof AST_Export)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        && tt.parent() === self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        hoisted.push(node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return make_node(AST_EmptyStatement, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        hoist_vars
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        && node instanceof AST_Var
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        && !node.definitions.some(def => def.name instanceof AST_Destructuring)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        node.definitions.forEach(function(def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            vars.set(def.name.name, def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            ++vars_found;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        var seq = node.to_assignments(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        var p = tt.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (p instanceof AST_ForIn && p.init === node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            if (seq == null) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                var def = node.definitions[0].name;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                return make_node(AST_SymbolRef, def, def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            return seq;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (p instanceof AST_For && p.init === node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            return seq;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (!seq) return make_node(AST_EmptyStatement, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return make_node(AST_SimpleStatement, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            body: seq
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (node instanceof AST_Scope)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return node; // to avoid descending in nested scopes
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        );
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = self.transform(tt);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (vars_found > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // collect only vars which don't show up in self's arguments list
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var defs = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const is_lambda = self instanceof AST_Lambda;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const args_as_names = is_lambda ? self.args_as_names() : null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            vars.forEach((def, name) => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (is_lambda && args_as_names.some((x) => x.name === def.name.name)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    vars.delete(name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    def = def.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    def.value = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    defs.push(def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    vars.set(name, def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (defs.length > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // try to merge in assignments
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (var i = 0; i < self.body.length;) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (self.body[i] instanceof AST_SimpleStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        var expr = self.body[i].body, sym, assign;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (expr instanceof AST_Assign
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && expr.operator == "="
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && (sym = expr.left) instanceof AST_Symbol
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && vars.has(sym.name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            var def = vars.get(sym.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            if (def.value) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            def.value = expr.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            remove(defs, def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            defs.push(def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            self.body.splice(i, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (expr instanceof AST_Sequence
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && (assign = expr.expressions[0]) instanceof AST_Assign
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && assign.operator == "="
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && (sym = assign.left) instanceof AST_Symbol
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            && vars.has(sym.name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            var def = vars.get(sym.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            if (def.value) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            def.value = assign.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            remove(defs, def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            defs.push(def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            self.body[i].body = make_sequence(expr, expr.expressions.slice(1));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (self.body[i] instanceof AST_EmptyStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.body.splice(i, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (self.body[i] instanceof AST_BlockStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.body.splice(i, 1, ...self.body[i].body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defs = make_node(AST_Var, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    definitions: defs
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                hoisted.push(defs);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.body = dirs.concat(hoisted, self.body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var self = this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var defs_by_id = new Map();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var hoister = new TreeTransformer(function(node, descend) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node instanceof AST_VarDef) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const sym = node.name;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let def;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (sym.scope === self
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && (def = sym.definition()).escaped != 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !def.assignments
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !def.direct_access
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !def.single_use
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !compressor.exposed(def)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !top_retain(def)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && (value = sym.fixed_value()) === node.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && value instanceof AST_Object
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !value.properties.some(prop =>
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    prop instanceof AST_Expansion || prop.computed_key()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                descend(node, this);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const defs = new Map();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const assignments = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value.properties.forEach(({ key, value }) => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    const scope = hoister.find_scope();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    const symbol = self.create_symbol(sym.CTOR, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        source: sym,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        scope,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        conflict_scopes: new Set([
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            scope,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            ...sym.definition().references.map(ref => ref.scope)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        ]),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        tentative_name: sym.name + "_" + key
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    defs.set(String(key), symbol.definition());
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    assignments.push(make_node(AST_VarDef, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        name: symbol,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defs_by_id.set(def.id, defs);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return MAP.splice(assignments);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (node instanceof AST_PropAccess
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && node.expression instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const defs = defs_by_id.get(node.expression.definition().id);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (defs) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const def = defs.get(String(get_simple_key(node.property)));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const sym = make_node(AST_SymbolRef, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    name: def.name,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    scope: node.expression.scope,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    thedef: def
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                sym.reference({});
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return sym;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self.transform(hoister);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_SimpleStatement, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("side_effects")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var body = self.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var node = body.drop_side_effect_free(compressor, true);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node !== body) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_SimpleStatement, self, { body: node });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_While, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Do, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("loops")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var cond = self.condition.tail_node().evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(cond instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (cond) return make_node(AST_For, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_BlockStatement, self.body, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.body,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!has_break_or_continue(self, compressor.parent())) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self.body, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.body,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function if_break_in_loop(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("dead_code") && is_break(first)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.init instanceof AST_Statement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(self.init);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (self.init) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(make_node(AST_SimpleStatement, self.init, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: self.init
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.condition) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        trim_unreachable_code(compressor, self.body, body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: body
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (first instanceof AST_If) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (is_break(first.body)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.condition) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = make_node(AST_Binary, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: first.condition.negate(compressor),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = first.condition.negate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            drop_it(first.alternative);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (is_break(first.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.condition) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = make_node(AST_Binary, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: first.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = first.condition;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            drop_it(first.body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_break(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node instanceof AST_Break
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && compressor.loopcontrol_target(node) === compressor.self();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function drop_it(rest) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        rest = as_statement_array(rest);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.body instanceof AST_BlockStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.body = self.body.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.body.body = rest.concat(self.body.body.slice(1));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.body = self.body.transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.body = make_node(AST_BlockStatement, self.body, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: rest
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = if_break_in_loop(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_For, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("loops")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("side_effects") && self.init) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.init = self.init.drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.condition) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var cond = self.condition.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!(cond instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (cond) self.condition = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            else if (!compressor.option("dead_code")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var orig = self.condition;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = make_node_from_constant(cond, self.condition);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.condition = best_of_expression(self.condition.transform(compressor), orig);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (compressor.option("dead_code")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!cond) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                trim_unreachable_code(compressor, self.body, body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.init instanceof AST_Statement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.push(self.init);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else if (self.init) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.push(make_node(AST_SimpleStatement, self.init, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        body: self.init
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body.push(make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return if_break_in_loop(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_If, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_empty(self.alternative)) self.alternative = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("conditionals")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // if condition can be statically determined, drop
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // one of the blocks.  note, statically determined implies
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // “has no side effects”; also it doesn't work for cases like
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // `x && true`, though it probably should.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var cond = self.condition.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("dead_code") && !(cond instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var orig = self.condition;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.condition = make_node_from_constant(cond, orig);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.condition = best_of_expression(self.condition.transform(compressor), orig);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("dead_code")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (cond instanceof AST_Node) cond = self.condition.tail_node().evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!cond) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            trim_unreachable_code(compressor, self.body, body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.alternative) body.push(self.alternative);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (!(cond instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: self.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.push(self.body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.alternative) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                trim_unreachable_code(compressor, self.alternative, body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var negated = self.condition.negate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var self_condition_length = self.condition.size();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var negated_length = negated.size();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var negated_is_best = negated_length < self_condition_length;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.alternative && negated_is_best) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        negated_is_best = false; // because we already do the switch here.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // no need to swap values of self_condition_length and negated_length
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // here because they are only used in an equality comparison later on.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.condition = negated;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var tmp = self.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.body = self.alternative || make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.alternative = tmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_empty(self.body) && is_empty(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_SimpleStatement, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: self.condition.clone()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.body instanceof AST_SimpleStatement
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.alternative instanceof AST_SimpleStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_SimpleStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                condition   : self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                consequent  : self.body.body,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                alternative : self.alternative.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self_condition_length === negated_length && !negated_is_best
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.condition instanceof AST_Binary && self.condition.operator == "||") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // although the code length of self.condition and negated are the same,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // negated does not require additional surrounding parentheses.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // see https://github.com/mishoo/UglifyJS2/issues/979
 | 
						
						
						
						
							 | 
							
								 | 
							
							            negated_is_best = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (negated_is_best) return make_node(AST_SimpleStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator : "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left     : negated,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right    : self.body.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_SimpleStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator : "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left     : self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right    : self.body.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.body instanceof AST_EmptyStatement
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.alternative instanceof AST_SimpleStatement) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_SimpleStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator : "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left     : self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right    : self.alternative.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.body instanceof AST_Exit
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.alternative instanceof AST_Exit
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.body.TYPE == self.alternative.TYPE) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(self.body.CTOR, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                condition   : self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                consequent  : self.body.value || make_node(AST_Undefined, self.body),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).transform(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.body instanceof AST_If
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.body.alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.alternative) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = make_node(AST_If, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: make_node(AST_Binary, self.condition, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: self.body.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: self.body.body,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: null
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (aborts(self.body)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.alternative) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var alt = self.alternative;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.alternative = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: [ self, alt ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (aborts(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var body = self.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.body = self.alternative;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.condition = negated_is_best ? negated : self.condition.negate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.alternative = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: [ self, body ]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Switch, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("switches")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var branch;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var value = self.expression.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(value instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var orig = self.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.expression = make_node_from_constant(value, orig);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.expression = best_of_expression(self.expression.transform(compressor), orig);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("dead_code")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (value instanceof AST_Node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = self.expression.tail_node().evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var decl = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var default_branch;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var exact_match;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        branch = self.body[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (branch instanceof AST_Default) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!default_branch) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                default_branch = branch;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                eliminate_branch(branch, body[body.length - 1]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (!(value instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var exp = branch.expression.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(exp instanceof AST_Node) && exp !== value) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                eliminate_branch(branch, body[body.length - 1]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (exp instanceof AST_Node) exp = branch.expression.tail_node().evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (exp === value) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                exact_match = branch;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (default_branch) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var default_index = body.indexOf(default_branch);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.splice(default_index, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    eliminate_branch(default_branch, body[default_index - 1]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    default_branch = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        body.push(branch);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self.body = body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    let default_or_exact = default_branch || exact_match;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    default_branch = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    exact_match = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // group equivalent branches so they will be located next to each other,
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // that way the next micro-optimization will merge them.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // ** bail micro-optimization if not a simple switch case with breaks
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (body.every((branch, i) =>
 | 
						
						
						
						
							 | 
							
								 | 
							
							        (branch === default_or_exact || branch.expression instanceof AST_Constant)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (branch.body.length === 0 || aborts(branch) || body.length - 1 === i))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (let i = 0; i < body.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const branch = body[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for (let j = i + 1; j < body.length; j++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const next = body[j];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (next.body.length === 0) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const last_branch = j === (body.length - 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const equivalentBranch = branches_equivalent(next, branch, false);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (equivalentBranch || (last_branch && branches_equivalent(next, branch, true))) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (!equivalentBranch && last_branch) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        next.body.push(make_node(AST_Break));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    // let's find previous siblings with inert fallthrough...
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    let x = j - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    let fallthroughDepth = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    while (x > i) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (is_inert_body(body[x--])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            fallthroughDepth++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    const plucked = body.splice(j - fallthroughDepth, 1 + fallthroughDepth);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.splice(i + 1, 0, ...plucked);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    i += plucked.length;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // merge equivalent branches in a row
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (let i = 0; i < body.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let branch = body[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (branch.body.length === 0) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!aborts(branch)) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (let j = i + 1; j < body.length; i++, j++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let next = body[j];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (next.body.length === 0) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                branches_equivalent(next, branch, false)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || (j === body.length - 1 && branches_equivalent(next, branch, true))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                branch.body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                branch = next;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // Prune any empty branches at the end of the switch statement.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let i = body.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (; i >= 0; i--) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let bbody = body[i].body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_break(bbody[bbody.length - 1], compressor)) bbody.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!is_inert_body(body[i])) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // i now points to the index of a branch that contains a body. By incrementing, it's
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // pointing to the first branch that's empty.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        i++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!default_or_exact || body.indexOf(default_or_exact) >= i) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // The default behavior is to do nothing. We can take advantage of that to
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // remove all case expressions that are side-effect free that also do
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // nothing, since they'll default to doing nothing. But we can't remove any
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // case expressions before one that would side-effect, since they may cause
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // the side-effect to be skipped.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for (let j = body.length - 1; j >= i; j--) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                let branch = body[j];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (branch === default_or_exact) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    default_or_exact = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else if (!branch.expression.has_side_effects(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // Prune side-effect free branches that fall into default.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    DEFAULT: if (default_or_exact) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let default_index = body.indexOf(default_or_exact);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let default_body_index = default_index;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (; default_body_index < body.length - 1; default_body_index++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!is_inert_body(body[default_body_index])) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (default_body_index < body.length - 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break DEFAULT;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let side_effect_index = body.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (; side_effect_index >= 0; side_effect_index--) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let branch = body[side_effect_index];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (branch === default_or_exact) continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (branch.expression.has_side_effects(compressor)) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If the default behavior comes after any side-effect case expressions,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // then we can fold all side-effect free cases into the default branch.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If the side-effect case is after the default, then any side-effect
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // free cases could prevent the side-effect from occurring.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (default_body_index > side_effect_index) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let prev_body_index = default_index - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for (; prev_body_index >= 0; prev_body_index--) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!is_inert_body(body[prev_body_index])) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let before = Math.max(side_effect_index, prev_body_index) + 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let after = default_index;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (side_effect_index > default_index) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // If the default falls into the same body as a side-effect
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // case, then we need preserve that case and only prune the
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // cases after it.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                after = side_effect_index;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body[side_effect_index].body = body[default_body_index].body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // The default will be the last branch.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                default_or_exact.body = body[default_body_index].body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Prune everything after the default (or last side-effect case)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // until the next case with a body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.splice(after + 1, default_body_index - after);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Prune everything before the default that falls into it.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body.splice(before, default_index - before);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // See if we can remove the switch entirely if all cases (the default) fall into the same case body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    DEFAULT: if (default_or_exact) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let i = body.findIndex(branch => !is_inert_body(branch));
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let caseBody;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // `i` is equal to one of the following:
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // - `-1`, there is no body in the switch statement.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // - `body.length - 1`, all cases fall into the same body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // - anything else, there are multiple bodies in the switch.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (i === body.length - 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // All cases fall into the case body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let branch = body[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (has_nested_break(self)) break DEFAULT;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // This is the last case body, and we've already pruned any breaks, so it's
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // safe to hoist.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            caseBody = make_node(AST_BlockStatement, branch, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: branch.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            branch.body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (i !== -1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // If there are multiple bodies, then we cannot optimize anything.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break DEFAULT;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let sideEffect = body.find(branch => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                branch !== default_or_exact
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && branch.expression.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            );
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If no cases cause a side-effect, we can eliminate the switch entirely.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!sideEffect) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: decl.concat(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    statement(self.expression),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    default_or_exact.expression ? statement(default_or_exact.expression) : [],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    caseBody || []
 | 
						
						
						
						
							 | 
							
								 | 
							
							                )
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If we're this far, either there was no body or all cases fell into the same body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If there was no body, then we don't need a default branch (because the default is
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // do nothing). If there was a body, we'll extract it to after the switch, so the
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // switch's new default is to do nothing and we can still prune it.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const default_index = body.indexOf(default_or_exact);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        body.splice(default_index, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        default_or_exact = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (caseBody) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Recurse into switch statement one more time so that we can append the case body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // outside of the switch. This recursion will only happen once since we've pruned
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // the default case.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: decl.concat(self, caseBody)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // If we fall here, there is a default branch somewhere, there are no case bodies,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // and there's a side-effect somewhere. Just let the below paths take care of it.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (body.length > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        body[0].body = decl.concat(body[0].body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (body.length == 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: decl.concat(statement(self.expression))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (body.length == 1 && !has_nested_break(self)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // This is the last case body, and we've already pruned any breaks, so it's
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // safe to hoist.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let branch = body[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_If, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "===",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: self.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: branch.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: make_node(AST_BlockStatement, branch, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: branch.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: null
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (body.length === 2 && default_or_exact && !has_nested_break(self)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let branch = body[0] === default_or_exact ? body[1] : body[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let exact_exp = default_or_exact.expression && statement(default_or_exact.expression);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (aborts(body[0])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Only the first branch body could have a break (at the last statement)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let first = body[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_break(first.body[first.body.length - 1], compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                first.body.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_If, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                condition: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "===",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: branch.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: make_node(AST_BlockStatement, branch, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body: branch.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                alternative: make_node(AST_BlockStatement, default_or_exact, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body: [].concat(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        exact_exp || [],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        default_or_exact.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    )
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let operator = "===";
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let consequent = make_node(AST_BlockStatement, branch, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: branch.body,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let always = make_node(AST_BlockStatement, default_or_exact, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: [].concat(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                exact_exp || [],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                default_or_exact.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (body[0] === default_or_exact) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator = "!==";
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let tmp = always;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            always = consequent;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent = tmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                make_node(AST_If, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    condition: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator: operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left: self.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right: branch.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    body: consequent,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    alternative: null
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ].concat(always)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function eliminate_branch(branch, prev) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (prev && !aborts(prev)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            prev.body = prev.body.concat(branch.body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            trim_unreachable_code(compressor, branch, decl);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function branches_equivalent(branch, prev, insertBreak) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let bbody = branch.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let pbody = prev.body;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (insertBreak) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            bbody = bbody.concat(make_node(AST_Break));
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (bbody.length !== pbody.length) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let bblock = make_node(AST_BlockStatement, branch, { body: bbody });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let pblock = make_node(AST_BlockStatement, prev, { body: pbody });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return bblock.equivalent_to(pblock);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function statement(expression) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_SimpleStatement, expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: expression
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function has_nested_break(root) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let has_break = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let tw = new TreeWalker(node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (has_break) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node instanceof AST_Lambda) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node instanceof AST_SimpleStatement) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!is_break(node, tw)) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let parent = tw.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                parent instanceof AST_SwitchBranch
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && parent.body[parent.body.length - 1] === node
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            has_break = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        root.walk(tw);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return has_break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_break(node, stack) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node instanceof AST_Break
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && stack.loopcontrol_target(node) === self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_inert_body(branch) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return !aborts(branch) && !make_node(AST_BlockStatement, branch, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: branch.body
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).has_side_effects(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Try, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tighten_body(self.body, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.bcatch && self.bfinally && self.bfinally.body.every(is_empty)) self.bfinally = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("dead_code") && self.body.every(is_empty)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var body = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.bcatch) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            trim_unreachable_code(compressor, self.bcatch, body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.bfinally) body.push(...self.bfinally.body);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_BlockStatement, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: body
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Definitions.DEFMETHOD("remove_initializers", function() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var decls = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    this.definitions.forEach(function(def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (def.name instanceof AST_SymbolDeclaration) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            def.value = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            decls.push(def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            walk(def.name, node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (node instanceof AST_SymbolDeclaration) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    decls.push(make_node(AST_VarDef, def, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        name: node,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: null
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    this.definitions = decls;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var reduce_vars = compressor.option("reduce_vars");
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var assignments = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (const def of this.definitions) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (def.value) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var name = make_node(AST_SymbolRef, def.name, def.name);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            assignments.push(make_node(AST_Assign, def, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator : "=",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                logical: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left     : name,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right    : def.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (reduce_vars) name.definition().fixed = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const thedef = def.name.definition();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        thedef.eliminated++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        thedef.replaced--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (assignments.length == 0) return null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return make_sequence(this, assignments);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Definitions, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.definitions.length == 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_EmptyStatement, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_VarDef, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.name instanceof AST_SymbolLet
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.value != null
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && is_undefined(self.value, compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.value = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Import, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Call, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var exp = self.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var fn = exp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    inline_array_like_spread(self.args);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var simple_args = self.args.every((arg) =>
 | 
						
						
						
						
							 | 
							
								 | 
							
							        !(arg instanceof AST_Expansion)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    );
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("reduce_vars")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && fn instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !has_annotation(self, _NOINLINE)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const fixed = fn.fixed_value();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!retain_top_func(fixed, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            fn = fixed;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var is_func = fn instanceof AST_Lambda;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_func && fn.pinned()) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unused")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && simple_args
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && is_func
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !fn.uses_arguments) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var pos = 0, last = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var i = 0, len = self.args.length; i < len; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (fn.argnames[i] instanceof AST_Expansion) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (has_flag(fn.argnames[i].expression, UNUSED)) while (i < len) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var node = self.args[i++].drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.args[pos++] = node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else while (i < len) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.args[pos++] = self.args[i++];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                last = pos;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var trim = i >= fn.argnames.length;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (trim || has_flag(fn.argnames[i], UNUSED)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var node = self.args[i].drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.args[pos++] = node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else if (!trim) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.args[pos++] = make_node(AST_Number, self.args[i], {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.args[pos++] = self.args[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            last = pos;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.args.length = last;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unsafe")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (exp instanceof AST_Dot && exp.start.value === "Array" && exp.property === "from" && self.args.length === 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const [argument] = self.args;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (argument instanceof AST_Array) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Array, argument, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    elements: argument.elements
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (is_undeclared_ref(exp)) switch (exp.name) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Array":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length != 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Array, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    elements: self.args
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (self.args[0] instanceof AST_Number && self.args[0].value <= 11) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const elements = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (let i = 0; i < self.args[0].value; i++) elements.push(new AST_Hole);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return new AST_Array({ elements });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Object":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Object, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    properties: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "String":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 0) return make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: ""
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length <= 1) return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: self.args[0],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: make_node(AST_String, self, { value: "" })
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Number":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 0) return make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 1 && compressor.option("unsafe_math")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: self.args[0],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Symbol":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 1 && self.args[0] instanceof AST_String && compressor.option("unsafe_symbols"))
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.args.length = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Boolean":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 0) return make_node(AST_False, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expression: make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: self.args[0],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "!"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "!"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "RegExp":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var params = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length >= 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.args.length <= 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.args.every((arg) => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var value = arg.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    params.push(value);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return arg !== value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && regexp_is_safe(params[0])
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                let [ source, flags ] = params;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                source = regexp_source_fix(new RegExp(source).source);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const rx = make_node(AST_RegExp, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    value: { source, flags }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (rx._eval(compressor) !== rx) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return rx;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (exp instanceof AST_Dot) switch(exp.property) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "toString":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 0 && !exp.expression.may_throw_on_access(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: make_node(AST_String, self, { value: "" }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: exp.expression
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "join":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (exp.expression instanceof AST_Array) EXIT: {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var separator;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.args.length > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    separator = self.args[0].evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (separator === self.args[0]) break EXIT; // not a constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var elements = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var consts = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (var i = 0, len = exp.expression.elements.length; i < len; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var el = exp.expression.elements[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (el instanceof AST_Expansion) break EXIT;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var value = el.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (value !== el) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        consts.push(value);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        if (consts.length > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            elements.push(make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                value: consts.join(separator)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            consts.length = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        elements.push(el);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (consts.length > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    elements.push(make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: consts.join(separator)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (elements.length == 0) return make_node(AST_String, self, { value: "" });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (elements.length == 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (elements[0].is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return elements[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return make_node(AST_Binary, elements[0], {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator : "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left     : make_node(AST_String, self, { value: "" }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right    : elements[0]
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (separator == "") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var first;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (elements[0].is_string(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        || elements[1].is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        first = elements.shift();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        first = make_node(AST_String, self, { value: "" });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return elements.reduce(function(prev, el) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return make_node(AST_Binary, el, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator : "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left     : prev,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right    : el
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }, first).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // need this awkward cloning to not affect original element
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // best_of will decide which one to get through.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var node = self.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                node.expression = node.expression.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                node.expression.expression = node.expression.expression.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                node.expression.expression.elements = elements;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return best_of(compressor, self, node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "charAt":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (exp.expression.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var arg = self.args[0];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var index = arg ? arg.evaluate(compressor) : 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (index !== arg) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return make_node(AST_Sub, exp, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        expression: exp.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        property: make_node_from_constant(index | 0, arg || exp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "apply":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.args.length == 2 && self.args[1] instanceof AST_Array) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var args = self.args[1].elements.slice();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                args.unshift(self.args[0]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Call, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: make_node(AST_Dot, exp, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        expression: exp.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        optional: false,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        property: "call"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    args: args
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "call":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var func = exp.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (func instanceof AST_SymbolRef) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                func = func.fixed_value();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (func instanceof AST_Lambda && !func.contains_this()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return (self.args.length ? make_sequence(this, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self.args[0],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    make_node(AST_Call, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        expression: exp.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        args: self.args.slice(1)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ]) : make_node(AST_Call, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: exp.expression,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    args: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unsafe_Function")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && is_undeclared_ref(exp)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && exp.name == "Function") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // new Function() => function(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.args.length == 0) return make_node(AST_Function, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            argnames: [],
 | 
						
						
						
						
							 | 
							
								 | 
							
							            body: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var nth_identifier = compressor.mangle_options && compressor.mangle_options.nth_identifier || base54;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.args.every((x) => x instanceof AST_String)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // quite a corner-case, but we can handle it:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            //   https://github.com/mishoo/UglifyJS2/issues/203
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // if the code argument is a constant, then we can minify it.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            try {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var code = "n(function(" + self.args.slice(0, -1).map(function(arg) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return arg.value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).join(",") + "){" + self.args[self.args.length - 1].value + "})";
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var ast = parse(code);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var mangle = { ie8: compressor.option("ie8"), nth_identifier: nth_identifier };
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ast.figure_out_scope(mangle);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var comp = new Compressor(compressor.options, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    mangle_options: compressor.mangle_options
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ast = ast.transform(comp);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ast.figure_out_scope(mangle);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ast.compute_char_frequency(mangle);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ast.mangle_names(mangle);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var fun;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                walk(ast, node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (is_func_expr(node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        fun = node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        return walk_abort;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var code = OutputStream();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                AST_BlockStatement.prototype._codegen.call(fun, fun, code);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.args = [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: fun.argnames.map(function(arg) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            return arg.print_to_string();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }).join(",")
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    make_node(AST_String, self.args[self.args.length - 1], {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: code.get().replace(/^{|}$/g, "")
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } catch (ex) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!(ex instanceof JS_Parse_Error)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    throw ex;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // Otherwise, it crashes at runtime. Or maybe it's nonstandard syntax.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return inline_into_call(self, fn, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_New, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        compressor.option("unsafe") &&
 | 
						
						
						
						
							 | 
							
								 | 
							
							        is_undeclared_ref(self.expression) &&
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ["Object", "RegExp", "Function", "Error", "Array"].includes(self.expression.name)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) return make_node(AST_Call, self, self).transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Sequence, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("side_effects")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var expressions = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    filter_for_side_effects();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var end = expressions.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    trim_right_for_undefined();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (end == 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self.expressions = expressions;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function filter_for_side_effects() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var first = first_in_statement(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var last = self.expressions.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.expressions.forEach(function(expr, index) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (index < last) expr = expr.drop_side_effect_free(compressor, first);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (expr) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                merge_sequence(expressions, expr);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                first = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function trim_right_for_undefined() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        while (end > 0 && is_undefined(expressions[end], compressor)) end--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (end < expressions.length - 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expressions[end] = make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator   : "void",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expression : expressions[end]
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expressions.length = end + 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("sequences")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.expression instanceof AST_Sequence) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var x = this.expression.expressions.slice();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var e = this.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            e.expression = x.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            x.push(e);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_sequence(this, x).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_UnaryPostfix, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self.lift_sequences(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_UnaryPrefix, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var e = self.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.operator == "delete" &&
 | 
						
						
						
						
							 | 
							
								 | 
							
							        !(
 | 
						
						
						
						
							 | 
							
								 | 
							
							            e instanceof AST_SymbolRef ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            e instanceof AST_PropAccess ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            e instanceof AST_Chain ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            is_identifier_atom(e)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_sequence(self, [e, make_node(AST_True, self)]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var seq = self.lift_sequences(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (seq !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return seq;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("side_effects") && self.operator == "void") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        e = e.drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (e) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = e;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Undefined, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        switch (self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "!":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (e instanceof AST_UnaryPrefix && e.operator == "!") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // !!foo ==> foo, if we're in boolean context
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return e.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (e instanceof AST_Binary) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor)));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "typeof":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // typeof always returns a non-empty string, thus it's
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // always true in booleans
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // And we don't need to check if it's undeclared, because in typeof, that's OK
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return (e instanceof AST_SymbolRef ? make_node(AST_True, self) : make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                e,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                make_node(AST_True, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ])).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.operator == "-" && e instanceof AST_Infinity) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        e = e.transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (e instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (self.operator == "+" || self.operator == "-")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: e.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: make_node(AST_UnaryPrefix, e.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expression: e.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: e.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // avoids infinite recursion of numerals
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.operator != "-"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || !(e instanceof AST_Number || e instanceof AST_Infinity || e instanceof AST_BigInt)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var ev = self.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (ev !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ev = make_node_from_constant(ev, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return best_of(compressor, ev, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Binary.DEFMETHOD("lift_sequences", function(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("sequences")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.left instanceof AST_Sequence) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var x = this.left.expressions.slice();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var e = this.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            e.left = x.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            x.push(e);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_sequence(this, x).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (this.right instanceof AST_Sequence && !this.left.has_side_effects(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var assign = this.operator == "=" && this.left instanceof AST_SymbolRef;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var x = this.right.expressions;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var last = x.length - 1;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for (var i = 0; i < last; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!assign && x[i].has_side_effects(compressor)) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (i == last) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                x = x.slice();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var e = this.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                e.right = x.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                x.push(e);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_sequence(this, x).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (i > 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var e = this.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                e.right = make_sequence(this.right, x.slice(i));
 | 
						
						
						
						
							 | 
							
								 | 
							
							                x = x.slice(0, i);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                x.push(e);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_sequence(this, x).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return this;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							var commutativeOperators = makePredicate("== === != !== * & | ^");
 | 
						
						
						
						
							 | 
							
								 | 
							
							function is_object(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return node instanceof AST_Array
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || node instanceof AST_Lambda
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || node instanceof AST_Object
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || node instanceof AST_Class;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Binary, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function reversible() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.left.is_constant()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || self.right.is_constant()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || !self.left.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !self.right.has_side_effects(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function reverse(op) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (reversible()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (op) self.operator = op;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var tmp = self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.left = self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.right = tmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (commutativeOperators.has(self.operator)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.right.is_constant()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && !self.left.is_constant()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // if right is a constant, whatever side effects the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // left side might have could not influence the
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // result.  hence, force switch.
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                  && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                reverse();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self = self.lift_sequences(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("comparisons")) switch (self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "===":
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "!==":
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var is_strict_comparison = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            (self.left.is_number(compressor) && self.right.is_number(compressor)) ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            (self.left.is_boolean() && self.right.is_boolean()) ||
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.left.equivalent_to(self.right)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.operator = self.operator.substr(0, 2);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // XXX: intentionally falling down to the next case
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "==":
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "!=":
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // void 0 == x => null == x
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!is_strict_comparison && is_undefined(self.left, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.left = make_node(AST_Null, self.left);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (compressor.option("typeofs")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // "undefined" == typeof x => undefined === x
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left instanceof AST_String
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.value == "undefined"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right instanceof AST_UnaryPrefix
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.operator == "typeof") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var expr = self.right.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.right = expr;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.left = make_node(AST_Undefined, self.left).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.operator.length == 2) self.operator += "=";
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (self.left instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // obj !== obj => false
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.definition() === self.right.definition()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && is_object(self.left.fixed_value())) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(self.operator[0] == "=" ? AST_True : AST_False, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "&&":
 | 
						
						
						
						
							 | 
							
								 | 
							
							      case "||":
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var lhs = self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (lhs.operator == self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            lhs = lhs.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (lhs instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && lhs.operator == (self.operator == "&&" ? "!==" : "===")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && lhs.operator == self.right.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && (is_undefined(lhs.left, compressor) && self.right.left instanceof AST_Null
 | 
						
						
						
						
							 | 
							
								 | 
							
							                || lhs.left instanceof AST_Null && is_undefined(self.right.left, compressor))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && !lhs.right.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && lhs.right.equivalent_to(self.right.right)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var combined = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: lhs.operator.slice(0, -1),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: make_node(AST_Null, self),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: lhs.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (lhs !== self.left) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                combined = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: combined
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return combined;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.operator == "+" && compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var ll = self.left.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var rr = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (ll && typeof ll == "string") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                make_node(AST_True, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (rr && typeof rr == "string") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                make_node(AST_True, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("comparisons") && self.is_boolean()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!(compressor.parent() instanceof AST_Binary)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || compressor.parent() instanceof AST_Assign) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var negated = make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "!",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expression: self.negate(compressor, first_in_statement(compressor))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self = best_of(compressor, self, negated);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (compressor.option("unsafe_comps")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            switch (self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							              case "<": reverse(">"); break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							              case "<=": reverse(">="); break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.operator == "+") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.right instanceof AST_String
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.getValue() == ""
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.left instanceof AST_String
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.getValue() == ""
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.operator == "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.left instanceof AST_String
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.left.left.getValue() == ""
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.left = self.left.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("evaluate")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        switch (self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "&&":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var ll = has_flag(self.left, TRUTHY)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ? true
 | 
						
						
						
						
							 | 
							
								 | 
							
							                : has_flag(self.left, FALSY)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ? false
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    : self.left.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!ll) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (!(ll instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var rr = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!rr) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        make_node(AST_False, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    set_flag(self, FALSY);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (!(rr instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var parent = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (parent.operator == "&&" && parent.left === compressor.self() || compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return self.left.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // x || false && y ---> x ? y : false
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left.operator == "||") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var lr = self.left.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!lr) return make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    condition: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    consequent: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    alternative: self.left.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "||":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var ll = has_flag(self.left, TRUTHY)
 | 
						
						
						
						
							 | 
							
								 | 
							
							              ? true
 | 
						
						
						
						
							 | 
							
								 | 
							
							              : has_flag(self.left, FALSY)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ? false
 | 
						
						
						
						
							 | 
							
								 | 
							
							                : self.left.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!ll) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (!(ll instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return maintain_this_binding(compressor.parent(), compressor.self(), self.left).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var rr = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!rr) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var parent = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (parent.operator == "||" && parent.left === compressor.self() || compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return self.left.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (!(rr instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        make_node(AST_True, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    set_flag(self, TRUTHY);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left.operator == "&&") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var lr = self.left.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    condition: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    consequent: self.left.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    alternative: self.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "??":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_nullish(self.left, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var ll = self.left.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(ll instanceof AST_Node)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // if we know the value for sure we can simply compute right away.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return ll == null ? self.right : self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const rr = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!(rr instanceof AST_Node) && !rr) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var associative = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        switch (self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "+":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // (x + "foo") + "bar" => x + "foobar"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.right instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.operator == "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var binary = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.left.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var r = binary.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (binary !== r) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right: r
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // (x + "foo") + ("bar" + y) => (x + "foobar") + y
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.operator == "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.is_string(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right.operator == "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right.is_string(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var binary = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.left.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.right.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var m = binary.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (binary !== m) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left: make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right: m
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right: self.right.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // a + -b => a - b
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.right instanceof AST_UnaryPrefix
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right.operator == "-"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.is_number(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "-",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.right.expression
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // -a + b => b - a
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left instanceof AST_UnaryPrefix
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.left.operator == "-"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && reversible()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right.is_number(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: "-",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.left.expression
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // `foo${bar}baz` + 1 => `foo${bar}baz1`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left instanceof AST_TemplateString) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var l = self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var r = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (r != self.right) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    l.segments[l.segments.length - 1].value += String(r);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return l;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // 1 + `foo${bar}baz` => `1foo${bar}baz`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.right instanceof AST_TemplateString) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var r = self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var l = self.left.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (l != self.left) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    r.segments[0].value = String(l) + r.segments[0].value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    return r;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // `1${bar}2` + `foo${bar}baz` => `1${bar}2foo${bar}baz`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left instanceof AST_TemplateString
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right instanceof AST_TemplateString) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var l = self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var segments = l.segments;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var r = self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                segments[segments.length - 1].value += r.segments[0].value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (var i = 1; i < r.segments.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    segments.push(r.segments[i]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return l;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "*":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            associative = compressor.option("unsafe_math");
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "&":
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "|":
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "^":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // a + +b => +b + a
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (self.left.is_number(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && self.right.is_number(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && reversible()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !(self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.left.operator != self.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var reversed = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.right instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && !(self.left instanceof AST_Constant)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = best_of(compressor, reversed, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = best_of(compressor, self, reversed);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (associative && self.is_number(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // a + (b + c) => (a + b) + c
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.right instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.right.operator == self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left: make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left: self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right: self.right.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            start: self.left.start,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            end: self.right.left.end
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right: self.right.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // (n + 2) + 3 => 5 + n
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // (2 * n) * 3 => 6 + n
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.right instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.left.operator == self.operator) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (self.left.left instanceof AST_Constant) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left: make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                left: self.left.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                right: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                start: self.left.left.start,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                end: self.right.end
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right: self.left.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    } else if (self.left.right instanceof AST_Constant) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left: make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                left: self.left.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                right: self.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                start: self.left.right.start,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                end: self.right.end
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right: self.left.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // (a | 1) | (2 | d) => (3 | a) | b
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.left instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.left.operator == self.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.left.right instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.right instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.right.operator == self.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && self.right.left instanceof AST_Constant) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    self = make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        left: make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            left: make_node(AST_Binary, self.left.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                operator: self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                left: self.left.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                right: self.right.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                start: self.left.right.start,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                end: self.right.left.end
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            right: self.left.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        right: self.right.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x && (y && z)  ==>  x && y && z
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x || (y || z)  ==>  x || y || z
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x + ("y" + z)  ==>  x + "y" + z
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // "x" + (y + "z")==>  "x" + y + "z"
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.right instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.right.operator == self.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (lazy_op.has(self.operator)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || (self.operator == "+"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && (self.right.left.is_string(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    || (self.left.is_string(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        && self.right.right.is_string(compressor)))))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.left = make_node(AST_Binary, self.left, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator : self.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left     : self.left.transform(compressor),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right    : self.right.left.transform(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.right = self.right.right.transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.transform(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var ev = self.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (ev !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ev = make_node_from_constant(ev, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return best_of(compressor, ev, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_SymbolExport, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_SymbolRef, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        !compressor.option("ie8")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && is_undeclared_ref(self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !compressor.find_parent(AST_With)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        switch (self.name) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "undefined":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Undefined, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "NaN":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_NaN, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Infinity":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Infinity, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const parent = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return inline_into_symbolref(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function is_atomic(lhs, self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Undefined, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unsafe_undefined")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var undef = find_variable(compressor, "undefined");
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (undef) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var ref = make_node(AST_SymbolRef, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name   : "undefined",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                scope  : undef.scope,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                thedef : undef
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            set_flag(ref, UNDEFINED);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return ref;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var lhs = is_lhs(compressor.self(), compressor.parent());
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (lhs && is_atomic(lhs, self)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        operator: "void",
 | 
						
						
						
						
							 | 
							
								 | 
							
							        expression: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        })
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Infinity, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var lhs = is_lhs(compressor.self(), compressor.parent());
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (lhs && is_atomic(lhs, self)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        compressor.option("keep_infinity")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !(lhs && !is_atomic(lhs, self))
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !find_variable(compressor, "Infinity")
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        operator: "/",
 | 
						
						
						
						
							 | 
							
								 | 
							
							        left: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							        right: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        })
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_NaN, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var lhs = is_lhs(compressor.self(), compressor.parent());
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (lhs && !is_atomic(lhs, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || find_variable(compressor, "NaN")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "/",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							const ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &");
 | 
						
						
						
						
							 | 
							
								 | 
							
							const ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &");
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Assign, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.logical) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.lift_sequences(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var def;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x = x ---> x
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.operator === "="
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.left instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.left.name !== "arguments"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !(def = self.left.definition()).undeclared
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.right.equivalent_to(self.left)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("dead_code")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.left instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var level = 0, node, parent = self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        do {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node = parent;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            parent = compressor.parent(level++);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (parent instanceof AST_Exit) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (in_try(level, parent)) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (is_reachable(def.scope, [ def ])) break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (self.operator == "=") return self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                def.fixed = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    operator: self.operator.slice(0, -1),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    left: self.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    right: self.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } while (parent instanceof AST_Binary && parent.right === node
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || parent instanceof AST_Sequence && parent.tail_node() === node);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self = self.lift_sequences(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // x = expr1 OP expr2
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.right.left instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.left.name == self.left.name
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && ASSIGN_OPS.has(self.right.operator)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // x = x - 2  --->  x -= 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.operator = self.right.operator + "=";
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.right = self.right.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (self.right.right instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && self.right.right.name == self.left.name
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && ASSIGN_OPS_COMMUTATIVE.has(self.right.operator)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && !self.right.left.has_side_effects(compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // x = 2 & x  --->  x &= 2
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.operator = self.right.operator + "=";
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.right = self.right.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function in_try(level, node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var right = self.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.right = make_node(AST_Null, right);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var may_throw = node.may_throw(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.right = right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var scope = self.left.definition().scope;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var parent;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        while ((parent = compressor.parent(level++)) !== scope) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (parent instanceof AST_Try) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (parent.bfinally) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (may_throw && parent.bcatch) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_DefaultAssign, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("evaluate")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var evaluateRight = self.right.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // `[x = undefined] = foo` ---> `[x] = foo`
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (evaluateRight === undefined) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = self.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    } else if (evaluateRight !== self.right) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        evaluateRight = make_node_from_constant(evaluateRight, self.right);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.right = best_of_expression(evaluateRight, self.right);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function is_nullish_check(check, check_subject, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (check_subject.may_throw(compressor)) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    let nullish_side;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // foo == null
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        check instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && check.operator === "=="
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // which side is nullish?
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (
 | 
						
						
						
						
							 | 
							
								 | 
							
							            (nullish_side = is_nullish(check.left, compressor) && check.left)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || (nullish_side = is_nullish(check.right, compressor) && check.right)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // is the other side the same as the check_subject
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (
 | 
						
						
						
						
							 | 
							
								 | 
							
							            nullish_side === check.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							                ? check.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							                : check.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ).equivalent_to(check_subject)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // foo === null || foo === undefined
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (check instanceof AST_Binary && check.operator === "||") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let null_cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let undefined_cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const find_comparison = cmp => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(
 | 
						
						
						
						
							 | 
							
								 | 
							
							                cmp instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && (cmp.operator === "===" || cmp.operator === "==")
 | 
						
						
						
						
							 | 
							
								 | 
							
							            )) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let found = 0;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            let defined_side;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (cmp.left instanceof AST_Null) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                found++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                null_cmp = cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defined_side = cmp.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (cmp.right instanceof AST_Null) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                found++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                null_cmp = cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defined_side = cmp.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_undefined(cmp.left, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                found++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                undefined_cmp = cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defined_side = cmp.right;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_undefined(cmp.right, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                found++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                undefined_cmp = cmp;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                defined_side = cmp.left;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (found !== 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!defined_side.equivalent_to(check_subject)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        };
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!find_comparison(check.left)) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!find_comparison(check.right)) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (null_cmp && undefined_cmp && null_cmp !== undefined_cmp) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Conditional, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("conditionals")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // This looks like lift_sequences(), should probably be under "sequences"
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.condition instanceof AST_Sequence) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var expressions = self.condition.expressions.slice();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.condition = expressions.pop();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        expressions.push(self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_sequence(self, expressions);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var cond = self.condition.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (cond !== self.condition) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (cond) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return maintain_this_binding(compressor.parent(), compressor.self(), self.consequent);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return maintain_this_binding(compressor.parent(), compressor.self(), self.alternative);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var negated = cond.negate(compressor, first_in_statement(compressor));
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (best_of(compressor, cond, negated) === negated) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self = make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: negated,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent: self.alternative,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: self.consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var condition = self.condition;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var consequent = self.consequent;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var alternative = self.alternative;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x?x:y --> x||y
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (condition instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && condition.definition() === consequent.definition()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // if (foo) exp = something; else exp = something_else;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    //                   |
 | 
						
						
						
						
							 | 
							
								 | 
							
							    //                   v
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // exp = foo ? something : something_else;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        consequent instanceof AST_Assign
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && alternative instanceof AST_Assign
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.operator === alternative.operator
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.logical === alternative.logical
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.left.equivalent_to(alternative.left)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (!self.condition.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || consequent.operator == "="
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !consequent.left.has_side_effects(compressor))
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Assign, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: consequent.operator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: consequent.left,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            logical: consequent.logical,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                condition: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                consequent: consequent.right,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                alternative: alternative.right
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x ? y(a) : y(b) --> y(x ? a : b)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var arg_index;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (consequent instanceof AST_Call
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && alternative.TYPE === consequent.TYPE
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.args.length > 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.args.length == alternative.args.length
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.expression.equivalent_to(alternative.expression)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.condition.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !consequent.expression.has_side_effects(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && typeof (arg_index = single_arg_diff()) == "number") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var node = consequent.clone();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        node.args[arg_index] = make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent: consequent.args[arg_index],
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: alternative.args[arg_index]
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // a ? b : c ? b : d --> (a || c) ? b : d
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (alternative instanceof AST_Conditional
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.equivalent_to(alternative.consequent)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: alternative.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent: consequent,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: alternative.alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // a == null ? b : a -> a ?? b
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        compressor.option("ecma") >= 2020 &&
 | 
						
						
						
						
							 | 
							
								 | 
							
							        is_nullish_check(condition, alternative, compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "??",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: alternative,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // a ? b : (c, b) --> (a || c), b
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (alternative instanceof AST_Sequence
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.equivalent_to(alternative.expressions[alternative.expressions.length - 1])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							            make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: make_sequence(self, alternative.expressions.slice(0, -1))
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // a ? b : (c && b) --> (a || c) && b
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (alternative instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && alternative.operator == "&&"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.equivalent_to(alternative.right)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: alternative.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x?y?z:a:a --> x&&y?z:a
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (consequent instanceof AST_Conditional
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.alternative.equivalent_to(alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Conditional, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            condition: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: consequent.condition
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent: consequent.consequent,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            alternative: alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x ? y : y --> x, y
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (consequent.equivalent_to(alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ]).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // x ? y || z : z --> x && y || z
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (consequent instanceof AST_Binary
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.operator == "||"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && consequent.right.equivalent_to(alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: self.condition,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: consequent.left
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const in_bool = compressor.in_boolean_context();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_true(self.consequent)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (is_false(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // c ? true : false ---> !!c
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return booleanize(self.condition);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // c ? true : x ---> !!c || x
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: booleanize(self.condition),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: self.alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_false(self.consequent)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (is_true(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // c ? false : true ---> !c
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return booleanize(self.condition.negate(compressor));
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // c ? false : x ---> !c && x
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: booleanize(self.condition.negate(compressor)),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: self.alternative
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_true(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // c ? x : true ---> !c || x
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "||",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: booleanize(self.condition.negate(compressor)),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: self.consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_false(self.alternative)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // c ? x : false ---> !!c && x
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "&&",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            left: booleanize(self.condition),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            right: self.consequent
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function booleanize(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node.is_boolean()) return node;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // !!expression
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_UnaryPrefix, node, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "!",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expression: node.negate(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // AST_True or !0
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_true(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node instanceof AST_True
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || in_bool
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.getValue()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || (node instanceof AST_UnaryPrefix
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.operator == "!"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.expression instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !node.expression.getValue());
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // AST_False or !1
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_false(node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return node instanceof AST_False
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || in_bool
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !node.getValue()
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || (node instanceof AST_UnaryPrefix
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.operator == "!"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.expression instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && node.expression.getValue());
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function single_arg_diff() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var a = consequent.args;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var b = alternative.args;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var i = 0, len = a.length; i < len; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (a[i] instanceof AST_Expansion) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!a[i].equivalent_to(b[i])) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (b[i] instanceof AST_Expansion) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (var j = i + 1; j < len; j++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (a[j] instanceof AST_Expansion) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (!a[j].equivalent_to(b[j])) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return i;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Boolean, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.in_boolean_context()) return make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value: +self.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var p = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("booleans_as_integers")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (p instanceof AST_Binary && (p.operator == "===" || p.operator == "!==")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            p.operator = p.operator.replace(/=$/, "");
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: +self.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("booleans")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (p instanceof AST_Binary && (p.operator == "=="
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                        || p.operator == "!=")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: +self.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_UnaryPrefix, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            operator: "!",
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expression: make_node(AST_Number, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: 1 - self.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            })
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function safe_to_flatten(value, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (value instanceof AST_SymbolRef) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        value = value.fixed_value();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!value) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(value instanceof AST_Lambda || value instanceof AST_Class)) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(value instanceof AST_Lambda && value.contains_this())) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return compressor.parent() instanceof AST_New;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("properties")) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (key === "__proto__") return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var expr = this.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (expr instanceof AST_Object) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var props = expr.properties;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var i = props.length; --i >= 0;) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var prop = props[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                const all_props_flattenable = props.every((p) =>
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    (p instanceof AST_ObjectKeyVal
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        || arrows && p instanceof AST_ConciseMethod && !p.is_generator
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    )
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    && !p.computed_key()
 | 
						
						
						
						
							 | 
							
								 | 
							
							                );
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!all_props_flattenable) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (!safe_to_flatten(prop.value, compressor)) return;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Sub, this, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: make_node(AST_Array, expr, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        elements: props.map(function(prop) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            var v = prop.value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            if (v instanceof AST_Accessor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                v = make_node(AST_Function, v, v);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            var k = prop.key;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                                return make_sequence(prop, [ k, v ]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							                            return v;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    property: make_node(AST_Number, this, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        value: i
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    })
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Sub, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var expr = self.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var prop = self.property;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("properties")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var key = prop.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (key !== prop) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (typeof key == "string") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (key == "undefined") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    key = undefined;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    var value = parseFloat(key);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (value.toString() == key) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                        key = value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var property = "" + key;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (is_basic_identifier_string(property)
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && property.length <= prop.size() + 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_node(AST_Dot, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    expression: expr,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    optional: self.optional,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    property: property,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    quote: prop.quote,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var fn;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    OPT_ARGUMENTS: if (compressor.option("arguments")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && expr instanceof AST_SymbolRef
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && expr.name == "arguments"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && expr.definition().orig.length == 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (fn = expr.scope) instanceof AST_Lambda
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && fn.uses_arguments
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !(fn instanceof AST_Arrow)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && prop instanceof AST_Number) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var index = prop.getValue();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var params = new Set();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var argnames = fn.argnames;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var n = 0; n < argnames.length; n++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(argnames[n] instanceof AST_SymbolFunarg)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break OPT_ARGUMENTS; // destructuring parameter - bail
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var param = argnames[n].name;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (params.has(param)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                break OPT_ARGUMENTS; // duplicate parameter - bail
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            params.add(param);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var argname = fn.argnames[index];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (argname && compressor.has_directive("use strict")) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var def = argname.definition();
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!compressor.option("reduce_vars") || def.assignments || def.orig.length > 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                argname = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            while (index >= fn.argnames.length) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                argname = fn.create_symbol(AST_SymbolFunarg, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    source: fn,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    scope: fn,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    tentative_name: "argument_" + fn.argnames.length,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                });
 | 
						
						
						
						
							 | 
							
								 | 
							
							                fn.argnames.push(argname);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (argname) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var sym = make_node(AST_SymbolRef, self, argname);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            sym.reference({});
 | 
						
						
						
						
							 | 
							
								 | 
							
							            clear_flag(argname, UNUSED);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return sym;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_lhs(self, compressor.parent())) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (key !== prop) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var sub = self.flatten_object(property, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (sub) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            expr = self.expression = sub.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            prop = self.property = sub.property;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("properties") && compressor.option("side_effects")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && prop instanceof AST_Number && expr instanceof AST_Array) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var index = prop.getValue();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var elements = expr.elements;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var retValue = elements[index];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        FLATTEN: if (safe_to_flatten(retValue, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var flatten = true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var values = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            for (var i = elements.length; --i > index;) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var value = elements[i].drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (value) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    values.unshift(value);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    if (flatten && value.has_side_effects(compressor)) flatten = false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (retValue instanceof AST_Expansion) break FLATTEN;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            retValue = retValue instanceof AST_Hole ? make_node(AST_Undefined, retValue) : retValue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!flatten) values.unshift(retValue);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            while (--i >= 0) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var value = elements[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (value instanceof AST_Expansion) break FLATTEN;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value = value.drop_side_effect_free(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                if (value) values.unshift(value);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                else index--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (flatten) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                values.push(retValue);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return make_sequence(self, values).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else return make_node(AST_Sub, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expression: make_node(AST_Array, expr, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    elements: values
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                property: make_node(AST_Number, prop, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    value: index
 | 
						
						
						
						
							 | 
							
								 | 
							
							                })
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var ev = self.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (ev !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ev = make_node_from_constant(ev, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return best_of(compressor, ev, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Chain, function (self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_nullish(self.expression, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        let parent = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // It's valid to delete a nullish optional chain, but if we optimized
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // this to `delete undefined` then it would appear to be a syntax error
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // when we try to optimize the delete. Thankfully, `delete 0` is fine.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (parent instanceof AST_UnaryPrefix && parent.operator === "delete") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node_from_constant(0, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_Undefined, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							AST_Lambda.DEFMETHOD("contains_this", function() {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return walk(this, node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (node instanceof AST_This) return walk_abort;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							            node !== this
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && node instanceof AST_Scope
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && !(node instanceof AST_Arrow)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    });
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Dot, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    const parent = compressor.parent();
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (is_lhs(self, parent)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unsafe_proto")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.expression instanceof AST_Dot
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.expression.property == "prototype") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var exp = self.expression.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (is_undeclared_ref(exp)) switch (exp.name) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Array":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_Array, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                elements: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Function":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_Function, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                argnames: [],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                body: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Number":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_Number, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: 0
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "Object":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_Object, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                properties: []
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "RegExp":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_RegExp, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: { source: "t", flags: "" }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							          case "String":
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.expression = make_node(AST_String, self.expression, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: ""
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							            break;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(parent instanceof AST_Call) || !has_annotation(parent, _NOINLINE)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const sub = self.flatten_object(self.property, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (sub) return sub.optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.expression instanceof AST_PropAccess
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && parent instanceof AST_PropAccess) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    let ev = self.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (ev !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ev = make_node_from_constant(ev, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return best_of(compressor, ev, self);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function literals_in_boolean_context(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.in_boolean_context()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return best_of(compressor, self, make_sequence(self, [
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            make_node(AST_True, self)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        ]).optimize(compressor));
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function inline_array_like_spread(elements) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (var i = 0; i < elements.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var el = elements[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (el instanceof AST_Expansion) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var expr = el.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expr instanceof AST_Array
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !expr.elements.some(elm => elm instanceof AST_Hole)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                elements.splice(i, 1, ...expr.elements);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // Step back one, as the element at i is now new.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                i--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // In array-like spread, spreading a non-iterable value is TypeError.
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // We therefore can’t optimize anything else, unlike with object spread.
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Array, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var optimized = literals_in_boolean_context(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (optimized !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return optimized;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    inline_array_like_spread(self.elements);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							function inline_object_prop_spread(props, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (var i = 0; i < props.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var prop = props[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (prop instanceof AST_Expansion) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            const expr = prop.expression;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							                expr instanceof AST_Object
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && expr.properties.every(prop => prop instanceof AST_ObjectKeyVal)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                props.splice(i, 1, ...expr.properties);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // Step back one, as the property at i is now new.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                i--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (expr instanceof AST_Constant
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !(expr instanceof AST_String)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // Unlike array-like spread, in object spread, spreading a
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // non-iterable value silently does nothing; it is thus safe
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // to remove. AST_String is the only iterable AST_Constant.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                props.splice(i, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                i--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            } else if (is_nullish(expr, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // Likewise, null and undefined can be silently removed.
 | 
						
						
						
						
							 | 
							
								 | 
							
							                props.splice(i, 1);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                i--;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Object, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var optimized = literals_in_boolean_context(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (optimized !== self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return optimized;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    inline_object_prop_spread(self.properties, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_RegExp, literals_in_boolean_context);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Return, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.value && is_undefined(self.value, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.value = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Arrow, opt_AST_Lambda);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Function, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self = opt_AST_Lambda(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("unsafe_arrows")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && compressor.option("ecma") >= 2015
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.name
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.is_generator
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.uses_arguments
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.pinned()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        const uses_this = walk(self, node => {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (node instanceof AST_This) return walk_abort;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!uses_this) return make_node(AST_Arrow, self, self).optimize(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Class, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // HACK to avoid compress failure.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // AST_Class is not really an AST_Scope/AST_Block as it lacks a body.
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_ClassStaticBlock, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    tighten_body(self.body, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Yield, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.expression && !self.is_star && is_undefined(self.expression, compressor)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        self.expression = null;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_TemplateString, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        !compressor.option("evaluate")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        || compressor.parent() instanceof AST_PrefixedTemplateString
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var segments = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							    for (var i = 0; i < self.segments.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var segment = self.segments[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (segment instanceof AST_Node) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var result = segment.evaluate(compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Evaluate to constant value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // Constant value shorter than ${segment}
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (result !== segment && (result + "").length <= segment.size() + "${}".length) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                // There should always be a previous and next segment if segment is a node
 | 
						
						
						
						
							 | 
							
								 | 
							
							                segments[segments.length - 1].value = segments[segments.length - 1].value + result + self.segments[++i].value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // `before ${`innerBefore ${any} innerAfter`} after` => `before innerBefore ${any} innerAfter after`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // TODO:
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // `before ${'test' + foo} after` => `before innerBefore ${any} innerAfter after`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            // `before ${foo + 'test} after` => `before innerBefore ${any} innerAfter after`
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (segment instanceof AST_TemplateString) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                var inners = segment.segments;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                segments[segments.length - 1].value += inners[0].value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							                for (var j = 1; j < inners.length; j++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    segment = inners[j];
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    segments.push(segment);
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }
 | 
						
						
						
						
							 | 
							
								 | 
							
							                continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        segments.push(segment);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    self.segments = segments;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // `foo` => "foo"
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (segments.length == 1) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_String, self, segments[0]);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (
 | 
						
						
						
						
							 | 
							
								 | 
							
							        segments.length === 3
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && segments[1] instanceof AST_Node
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (
 | 
						
						
						
						
							 | 
							
								 | 
							
							            segments[1].is_string(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || segments[1].is_number(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || is_nullish(segments[1], compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            || compressor.option("unsafe")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        )
 | 
						
						
						
						
							 | 
							
								 | 
							
							    ) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // `foo${bar}` => "foo" + bar
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (segments[2].value === "") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    value: segments[0].value,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: segments[1],
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        // `${bar}baz` => bar + "baz"
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (segments[0].value === "") {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_Binary, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                operator: "+",
 | 
						
						
						
						
							 | 
							
								 | 
							
							                left: segments[1],
 | 
						
						
						
						
							 | 
							
								 | 
							
							                right: make_node(AST_String, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    value: segments[2].value,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_PrefixedTemplateString, function(self) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							// ["p"]:1 ---> p:1
 | 
						
						
						
						
							 | 
							
								 | 
							
							// [42]:1 ---> 42:1
 | 
						
						
						
						
							 | 
							
								 | 
							
							function lift_key(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!compressor.option("computed_props")) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // save a comparison in the typical case
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (!(self.key instanceof AST_Constant)) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // allow certain acceptable props as not all AST_Constants are true constants
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (self.key instanceof AST_String || self.key instanceof AST_Number) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.key.value === "__proto__") return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self.key.value == "constructor"
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && compressor.parent() instanceof AST_Class) return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (self instanceof AST_ObjectKeyVal) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.quote = self.key.quote;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.key = self.key.value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else if (self instanceof AST_ClassProperty) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.quote = self.key.quote;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.key = make_node(AST_SymbolClassProperty, self.key, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name: self.key.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        } else {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.quote = self.key.quote;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.key = make_node(AST_SymbolMethod, self.key, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                name: self.key.value
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							}
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_ObjectProperty, lift_key);
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_ConciseMethod, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lift_key(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p(){return x;} ---> p:()=>x
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("arrows")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && compressor.parent() instanceof AST_Object
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.is_generator
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.value.uses_arguments
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.value.pinned()
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.value.body.length == 1
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.value.body[0] instanceof AST_Return
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && self.value.body[0].value
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.value.contains_this()) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var arrow = make_node(AST_Arrow, self.value, self.value);
 | 
						
						
						
						
							 | 
							
								 | 
							
							        arrow.async = self.async;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        arrow.is_generator = self.is_generator;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return make_node(AST_ObjectKeyVal, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            key: self.key instanceof AST_SymbolMethod ? self.key.name : self.key,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            value: arrow,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            quote: self.quote,
 | 
						
						
						
						
							 | 
							
								 | 
							
							        });
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_ObjectKeyVal, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    lift_key(self, compressor);
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p:function(){} ---> p(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p:function*(){} ---> *p(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p:async function(){} ---> async p(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p:()=>{} ---> p(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    // p:async()=>{} ---> async p(){}
 | 
						
						
						
						
							 | 
							
								 | 
							
							    var unsafe_methods = compressor.option("unsafe_methods");
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (unsafe_methods
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && compressor.option("ecma") >= 2015
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && (!(unsafe_methods instanceof RegExp) || unsafe_methods.test(self.key + ""))) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var key = self.key;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var value = self.value;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var is_arrow_with_block = value instanceof AST_Arrow
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && Array.isArray(value.body)
 | 
						
						
						
						
							 | 
							
								 | 
							
							            && !value.contains_this();
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if ((is_arrow_with_block || value instanceof AST_Function) && !value.name) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            return make_node(AST_ConciseMethod, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                async: value.async,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                is_generator: value.is_generator,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                key: key instanceof AST_Node ? key : make_node(AST_SymbolMethod, self, {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                    name: key,
 | 
						
						
						
						
							 | 
							
								 | 
							
							                }),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                value: make_node(AST_Accessor, value, value),
 | 
						
						
						
						
							 | 
							
								 | 
							
							                quote: self.quote,
 | 
						
						
						
						
							 | 
							
								 | 
							
							            });
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							def_optimize(AST_Destructuring, function(self, compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    if (compressor.option("pure_getters") == true
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && compressor.option("unused")
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !self.is_array
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && Array.isArray(self.names)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !is_destructuring_export_decl(compressor)
 | 
						
						
						
						
							 | 
							
								 | 
							
							        && !(self.names[self.names.length - 1] instanceof AST_Expansion)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var keep = [];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var i = 0; i < self.names.length; i++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var elem = self.names[i];
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!(elem instanceof AST_ObjectKeyVal
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && typeof elem.key == "string"
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && elem.value instanceof AST_SymbolDeclaration
 | 
						
						
						
						
							 | 
							
								 | 
							
							                && !should_retain(compressor, elem.value.definition()))) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                keep.push(elem);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (keep.length != self.names.length) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            self.names = keep;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							    return self;
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function is_destructuring_export_decl(compressor) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        var ancestors = [/^VarDef$/, /^(Const|Let|Var)$/, /^Export$/];
 | 
						
						
						
						
							 | 
							
								 | 
							
							        for (var a = 0, p = 0, len = ancestors.length; a < len; p++) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							            var parent = compressor.parent(p);
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!parent) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (a === 0 && parent.TYPE == "Destructuring") continue;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            if (!ancestors[a].test(parent.TYPE)) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							            }
 | 
						
						
						
						
							 | 
							
								 | 
							
							            a++;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							    function should_retain(compressor, def) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (def.references.length) return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (!def.global) return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        if (compressor.toplevel.vars) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							             if (compressor.top_retain) {
 | 
						
						
						
						
							 | 
							
								 | 
							
							                 return compressor.top_retain(def);
 | 
						
						
						
						
							 | 
							
								 | 
							
							             }
 | 
						
						
						
						
							 | 
							
								 | 
							
							             return false;
 | 
						
						
						
						
							 | 
							
								 | 
							
							        }
 | 
						
						
						
						
							 | 
							
								 | 
							
							        return true;
 | 
						
						
						
						
							 | 
							
								 | 
							
							    }
 | 
						
						
						
						
							 | 
							
								 | 
							
							});
 | 
						
						
						
						
							 | 
							
								 | 
							
							
 | 
						
						
						
						
							 | 
							
								 | 
							
							export {
 | 
						
						
						
						
							 | 
							
								 | 
							
							    Compressor,
 | 
						
						
						
						
							 | 
							
								 | 
							
							};
 |