Lines Matching defs:self
273 OPT(AST_Node, function(self, compressor) {
274 return self;
307 var self = this;
329 if (node !== self) return node;
348 self.transform(tt);
351 var self = this;
352 switch (self.body.length) {
354 return make_node(AST_UnaryPrefix, self, {
356 expression: make_node(AST_Number, self, { value: 0 }),
359 var stat = self.body[0];
363 return make_node(AST_Call, self, {
364 expression: make_node(AST_Function, self, {
366 body: self.body,
367 }).init_vars(self),
373 var self = this;
374 if (!is_statement(self)) self = make_node(AST_SimpleStatement, self, { body: self });
375 if (!(self instanceof AST_Toplevel)) self = make_node(AST_Toplevel, self, { body: [ self ] });
376 return self;
1734 var level = 0, node = compressor.self();
2054 var block = compressor.self(), level = 0, stat;
2089 var node = compressor.self(), level = 0;
2704 var iife = compressor.parent(), fn = compressor.self();
3540 var self = compressor.self();
3542 var in_iife = in_lambda && parent && parent.TYPE == "Call" && parent.expression === self;
3552 && drop_return_void && !(self instanceof AST_SwitchBranch)) {
3608 if (!in_lambda || self instanceof AST_Block && self.body === statements) {
3633 var stats = make_node(AST_BlockStatement, self, { body: statements.slice(i + 1) });
3637 var stats = make_node(AST_BlockStatement, self, { body: statements.slice(i + 1) });
3688 stat.alternative = make_node(AST_BlockStatement, self, {
3689 body: extract_functions().concat(make_node(AST_Return, self, { value: null })),
3746 if (!(self instanceof AST_SwitchBranch)) return true;
3753 if (self instanceof AST_SwitchBranch) {
3911 var self = compressor.self();
3912 if (self instanceof AST_Catch) {
3913 self = compressor.parent();
3914 } else if (self instanceof AST_LabeledStatement) {
3915 self = self.body;
3921 if (loop_body(lct) !== self
5648 var self = this.clone(), op = this.operator;
5651 case "<=" : self.operator = ">" ; return self;
5652 case "<" : self.operator = ">=" ; return self;
5653 case ">=" : self.operator = "<" ; return self;
5654 case ">" : self.operator = "<=" ; return self;
5658 case "==" : self.operator = "!="; return self;
5659 case "!=" : self.operator = "=="; return self;
5660 case "===": self.operator = "!=="; return self;
5661 case "!==": self.operator = "==="; return self;
5663 self.operator = "||";
5664 self.left = self.left.negate(compressor, first_in_statement);
5665 self.right = self.right.negate(compressor);
5666 return best(this, self, first_in_statement);
5668 self.operator = "&&";
5669 self.left = self.left.negate(compressor, first_in_statement);
5670 self.right = self.right.negate(compressor);
5671 return best(this, self, first_in_statement);
5679 var self = this.clone();
5680 self.consequent = self.consequent.negate(compressor);
5681 self.alternative = self.alternative.negate(compressor);
5682 return best(this, self, first_in_statement);
6106 var self = this;
6109 self.walk(new TreeWalker(function(node, descend) {
6112 if (node === self) return;
6119 if (self.inlined || node.redef || node.in_arg) {
6123 if (self.variables.has(node.name)) return true;
6137 if (is_arrow(self) && all(scopes, function(s) {
6181 OPT(AST_Directive, function(self, compressor) {
6183 && (!directives[self.value] || compressor.has_directive(self.value) !== self)) {
6184 return make_node(AST_EmptyStatement, self);
6186 return self;
6189 OPT(AST_Debugger, function(self, compressor) {
6191 return make_node(AST_EmptyStatement, self);
6192 return self;
6195 OPT(AST_LabeledStatement, function(self, compressor) {
6196 if (self.body instanceof AST_If || self.body instanceof AST_Break) {
6197 var body = tighten_body([ self.body ], compressor);
6200 self.body = make_node(AST_EmptyStatement, self);
6203 self.body = body[0];
6206 self.body = make_node(AST_BlockStatement, self, { body: body });
6210 return compressor.option("unused") && self.label.references.length == 0 ? self.body : self;
6213 OPT(AST_LoopControl, function(self, compressor) {
6214 if (!compressor.option("dead_code")) return self;
6215 var label = self.label;
6217 var lct = compressor.loopcontrol_target(self);
6218 self.label = null;
6219 if (compressor.loopcontrol_target(self) === lct) {
6220 remove(label.thedef.references, self);
6222 self.label = label;
6225 return self;
6228 OPT(AST_Block, function(self, compressor) {
6229 self.body = tighten_body(self.body, compressor);
6230 return self;
6246 OPT(AST_BlockStatement, function(self, compressor) {
6247 self.body = tighten_body(self.body, compressor);
6248 return trim_block(self, compressor.parent());
6260 OPT(AST_Lambda, function(self, compressor) {
6261 drop_rest_farg(self, compressor);
6262 self.body = tighten_body(self.body, compressor);
6263 return self;
6266 function opt_arrow(self, compressor) {
6267 if (!compressor.option("arrows")) return self;
6268 drop_rest_farg(self, compressor);
6269 if (self.value) self.body = [ self.first_statement() ];
6270 var body = tighten_body(self.body, compressor);
6275 self.body.length = 0;
6276 self.value = stat.value;
6280 self.body = body;
6281 self.value = null;
6284 return self;
6289 OPT(AST_Function, function(self, compressor) {
6290 drop_rest_farg(self, compressor);
6291 self.body = tighten_body(self.body, compressor);
6293 if (compressor.option("inline")) for (var i = 0; i < self.body.length; i++) {
6294 var stat = self.body[i];
6297 if (i != self.body.length - 1) break;
6304 } else if (self.name && self.name.definition() === exp.definition()) {
6313 if (fn.parent_scope !== self) break;
6315 return def.scope !== self;
6320 && parent.value === compressor.self()) break;
6324 if (len > self.argnames.length) break;
6325 if (!all(self.argnames, function(argname) {
6334 if (arg.definition() !== self.argnames[j].definition()) break;
6341 if (len < self.argnames.length && !compressor.drop_fargs(self, parent)) {
6345 } while (++len < self.argnames.length);
6351 return self;
6357 var in_arg = [], in_try, root, segment = {}, self = this;
6485 if (node === self) root = segment;
6654 self.walk(tw);
6771 } else if ((ldef = self.variables.get(def.name)) !== def) {
6788 if (seg.block !== self) return references[def.id] = false;
6870 var self = this;
6871 var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
6872 var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
6908 find_variable = compose(self, 0, noop);
6935 if (self instanceof AST_Toplevel && compressor.top_retain) {
6936 self.variables.each(function(def) {
6959 if (node === self) return;
6960 if (scope === self) {
7067 self.walk(tw);
7243 if (scope !== self) return;
7244 if (drop_funcs && node !== self && node instanceof AST_DefClass) {
7261 if (drop_funcs && node !== self && node instanceof AST_LambdaDefinition) {
7705 self.transform(tt);
7706 if (self instanceof AST_Lambda
7707 && self.body.length == 1
7708 && self.body[0] instanceof AST_Directive
7709 && self.body[0].value == "use strict") {
7710 self.body.length = 0;
7744 if (def.scope.resolve() !== self) return false;
7812 if (def.scope.resolve() === self) assignments.add(def.id, node);
7817 if (def.scope.resolve() === self) assignments.add(def.id, node);
7822 if (node_def.scope.resolve() !== self && self.variables.get(sym.name) !== node_def) return;
7823 if (is_arguments(node_def) && !all(self.argnames, function(argname) {
7874 if (node.init instanceof AST_SymbolRef && scope === self) {
7884 if (def.scope.resolve() !== self) {
8246 var self = this;
8251 self.walk(new TreeWalker(function(node) {
8254 if (node instanceof AST_Scope && node !== self) return true;
8268 if (node === self) return;
8278 if (p !== self && compressor.has_directive("use strict")) return node;
8290 && self.find_variable(sym.name) === sym.definition();
8311 self.transform(tt);
8313 // collect only vars which don't show up in self's arguments list
8315 if (self instanceof AST_Lambda) self.each_argname(function(argname) {
8328 if (defns.length > 0) hoisted.push(make_node(AST_Var, self, { definitions: defns }));
8330 self.body = dirs.concat(hoisted, self.body);
8501 var self = this;
8502 if (is_arrow(self) && self.value) return;
8503 var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;
8522 scope: self,
8534 self.body.splice(self.body.indexOf(tt.stack[1]) + 1, 0, make_node(AST_Var, node, {
8540 if (node === self) return;
8565 var new_var = self.make_var(type, sym, sym.name + "_" + key);
8570 self.transform(tt);
8571 self.transform(new TreeTransformer(function(node, descend) {
8600 if (self.find_variable(sym.name) !== def) return;
8857 var self = this;
8858 if (self.is_expr_pure(compressor)) {
8859 if (self.pure) AST_Node.warn("Dropping __PURE__ call [{start}]", self);
8860 var args = trim(self.args, compressor, first_in_statement, array_spread);
8861 return args && make_sequence(self, args.map(convert_spread));
8863 var exp = self.expression;
8864 if (self.is_call_pure(compressor)) {
8865 var exprs = self.args.slice();
8868 return exprs && make_sequence(self, exprs.map(convert_spread));
8871 var call = self.clone();
8880 self = self.clone();
8881 self.expression = dropped;
8883 if (exp._squeezed) self.expression._squeezed = true;
8885 if (self instanceof AST_New) {
8890 var exprs = self.args.slice();
8893 return exprs && make_sequence(self, exprs.map(convert_spread));
8896 self = make_node(AST_Call, self);
8897 self.expression = self.expression.clone();
8898 self.args = self.args.slice();
8902 self.call_only = true;
8903 return self;
8906 var self = this;
8908 var props = self.properties;
8915 if (value.contains_this()) return self;
8923 var base = self.extends;
8927 if (!base) exprs.unshift(self.extends);
8933 if (!base && !values && !self.name) return null;
8936 if (base || self.name || !compressor.has_directive("use strict")) {
8937 var node = to_class_expr(self);
8942 if (exprs.length) values.unshift(make_node(AST_ClassField, self, {
8943 key: make_sequence(self, exprs),
8947 } else node.properties.push(make_node(AST_ClassField, self, {
8949 key: exprs.length ? make_sequence(self, exprs) : "c",
8952 } else if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, {
8953 key: make_sequence(self, exprs),
8954 value: make_node(AST_Function, self, {
8961 if (values) exprs.push(make_node(AST_Call, self, {
8962 expression: make_node(AST_Arrow, self, {
8966 }).init_vars(self.parent_scope),
8969 return make_sequence(self, exprs);
8972 return make_sequence(self, values.map(function(node) {
9094 var self = this;
9095 if (self.is_expr_pure(compressor)) {
9096 var expressions = self.expressions;
9098 return make_sequence(self, expressions).drop_side_effect_free(compressor, first_in_statement);
9100 var tag = self.tag;
9104 self = self.clone();
9105 self.tag = dropped;
9107 if (tag._squeezed) self.tag._squeezed = true;
9109 return self;
9131 OPT(AST_SimpleStatement, function(self, compressor) {
9133 var body = self.body;
9136 AST_Node.warn("Dropping side-effect-free statement [{start}]", self);
9137 return make_node(AST_EmptyStatement, self);
9140 return make_node(AST_SimpleStatement, self, { body: node });
9143 return self;
9146 OPT(AST_While, function(self, compressor) {
9147 return compressor.option("loops") ? make_node(AST_For, self).optimize(compressor) : self;
9165 OPT(AST_Do, function(self, compressor) {
9166 if (!compressor.option("loops")) return self;
9167 var cond = fuzzy_eval(compressor, self.condition);
9169 if (cond && !has_loop_control(self, compressor.parent(), AST_Continue)) return make_node(AST_For, self, {
9170 body: make_node(AST_BlockStatement, self.body, {
9172 self.body,
9173 make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
9177 if (!has_loop_control(self, compressor.parent())) return make_node(AST_BlockStatement, self.body, {
9179 self.body,
9180 make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
9184 if (self.body instanceof AST_BlockStatement && !has_loop_control(self, compressor.parent(), AST_Continue)) {
9185 var body = self.body.body;
9191 && compressor.loopcontrol_target(stat.body) === self) {
9193 self.condition = make_node(AST_Binary, self, {
9196 right: self.condition,
9201 self.condition = make_sequence(self, [
9203 self.condition,
9210 self.body = trim_block(self.body, compressor.parent());
9212 if (self.body instanceof AST_EmptyStatement) return make_node(AST_For, self).optimize(compressor);
9213 if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {
9214 condition: make_sequence(self.condition, [
9215 self.body.body,
9216 self.condition,
9218 body: make_node(AST_EmptyStatement, self),
9220 return self;
9227 if (!member(node.definition(), self.enclosed)) found = true;
9235 function if_break_in_loop(self, compressor) {
9236 var first = first_statement(self.body);
9242 if (is_statement(self.init)) {
9243 body.push(self.init);
9244 } else if (self.init) {
9245 body.push(make_node(AST_SimpleStatement, self.init, { body: self.init }));
9248 if (self.condition && retain) {
9249 body.push(make_node(AST_If, self, {
9250 condition: self.condition,
9254 } else if (self.condition) {
9255 body.push(make_node(AST_SimpleStatement, self.condition, { body: self.condition }));
9259 extract_declarations_from_unreachable_code(compressor, self.body, body);
9260 return make_node(AST_BlockStatement, self, { body: body });
9265 if (self.condition) {
9266 self.condition = make_node(AST_Binary, self.condition, {
9267 left: self.condition,
9272 self.condition = first.condition.negate(compressor);
9280 if (self.condition) {
9281 self.condition = make_node(AST_Binary, self.condition, {
9282 left: self.condition,
9287 self.condition = first.condition;
9294 return self;
9301 return compressor.loopcontrol_target(node) !== compressor.self();
9305 if (self.body instanceof AST_BlockStatement) {
9306 self.body = self.body.clone();
9307 self.body.body = rest.concat(self.body.body.slice(1));
9308 self.body = self.body.transform(compressor);
9310 self.body = make_node(AST_BlockStatement, self.body, { body: rest }).transform(compressor);
9312 return if_break_in_loop(self, compressor);
9316 OPT(AST_For, function(self, compressor) {
9317 if (!compressor.option("loops")) return self;
9319 if (self.init) self.init = self.init.drop_side_effect_free(compressor);
9320 if (self.step) self.step = self.step.drop_side_effect_free(compressor);
9322 if (self.condition) {
9323 var cond = fuzzy_eval(compressor, self.condition);
9327 if (is_statement(self.init)) {
9328 body.push(self.init);
9329 } else if (self.init) {
9330 body.push(make_node(AST_SimpleStatement, self.init, { body: self.init }));
9332 body.push(make_node(AST_SimpleStatement, self.condition, { body: self.condition }));
9333 extract_declarations_from_unreachable_code(compressor, self.body, body);
9334 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
9337 self.body = make_node(AST_BlockStatement, self.body, {
9339 make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
9340 self.body,
9343 self.condition = null;
9346 return if_break_in_loop(self, compressor);
9349 OPT(AST_ForEnumeration, function(self, compressor) {
9350 if (compressor.option("varify") && is_lexical_definition(self.init)) {
9351 var name = self.init.definitions[0].name;
9359 self.init = to_var(self.init, self.resolve());
9362 return self;
9496 var parent = compressor.self();
9567 OPT(AST_If, function(self, compressor) {
9568 if (is_empty(self.alternative)) self.alternative = null;
9570 if (!compressor.option("conditionals")) return self;
9571 if (compressor.option("booleans") && !self.condition.has_side_effects(compressor)) {
9572 mark_duplicate_condition(compressor, self.condition);
9579 var cond = fuzzy_eval(compressor, self.condition);
9581 AST_Node.warn("Condition always false [{start}]", self.condition);
9583 make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),
9585 extract_declarations_from_unreachable_code(compressor, self.body, body);
9586 if (self.alternative) body.push(self.alternative);
9587 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
9589 AST_Node.warn("Condition always true [{start}]", self.condition);
9591 make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),
9592 self.body,
9594 if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);
9595 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
9598 var negated = self.condition.negate(compressor);
9599 var self_condition_length = self.condition.print_to_string().length;
9602 if (self.alternative && negated_is_best) {
9606 self.condition = negated;
9607 var tmp = self.body;
9608 self.body = self.alternative;
9609 self.alternative = is_empty(tmp) ? null : tmp;
9614 var body_exprs = sequencesize(self.body, body_defuns, body_var_defs, body_refs);
9618 var alt_exprs = sequencesize(self.alternative, alt_defuns, alt_var_defs, alt_refs);
9625 self.body = body_exprs;
9627 self.body = make_node(AST_EmptyStatement, self.body);
9629 self.body = make_node(AST_SimpleStatement, self.body, {
9630 body: make_sequence(self.body, body_exprs),
9639 self.alternative = alt_exprs;
9641 self.alternative = null;
9643 self.alternative = make_node(AST_SimpleStatement, self.alternative, {
9644 body: make_sequence(self.alternative, alt_exprs),
9649 if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
9651 body.push(self.transform(compressor));
9652 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
9656 if (body_var_defs.length > 0 || alt_var_defs.length > 0) body.push(make_node(AST_Var, self, {
9660 body.push(make_node(AST_SimpleStatement, self.condition, {
9661 body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
9663 left: self.condition,
9664 right: make_sequence(self.alternative, alt_exprs),
9665 }).transform(compressor) : self.condition.clone(),
9669 && self.condition instanceof AST_Binary && self.condition.operator == "||") {
9670 // although the code length of self.condition and negated are the same,
9675 body.push(make_node(AST_SimpleStatement, self, {
9676 body: make_node(AST_Binary, self, {
9678 left: negated_is_best ? negated : self.condition,
9679 right: make_sequence(self.body, body_exprs),
9683 body.push(make_node(AST_SimpleStatement, self, {
9684 body: make_node(AST_Conditional, self, {
9685 condition: self.condition,
9686 consequent: make_sequence(self.body, body_exprs),
9687 alternative: make_sequence(self.alternative, alt_exprs),
9693 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
9695 if (is_empty(self.body)) self = make_node(AST_If, self, {
9697 body: self.alternative,
9700 if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
9701 var cons_value = self.body.value;
9702 var alt_value = self.alternative.value;
9703 if (!cons_value && !alt_value) return make_node(AST_BlockStatement, self, {
9705 make_node(AST_SimpleStatement, self, { body: self.condition }),
9706 self.body,
9710 var exit = make_node(self.body.CTOR, self, {
9711 value: make_node(AST_Conditional, self, {
9712 condition: self.condition,
9713 consequent: cons_value || make_node(AST_Undefined, self.body).transform(compressor),
9714 alternative: alt_value || make_node(AST_Undefined, self.alternative).transform(compressor),
9717 if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;
9721 if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
9722 self = make_node(AST_If, self, {
9723 condition: make_node(AST_Binary, self.condition, {
9725 left: self.condition,
9726 right: self.body.condition,
9728 body: self.body.body,
9732 if (aborts(self.body) && self.alternative) {
9733 var alt = self.alternative;
9734 self.alternative = null;
9735 return make_node(AST_BlockStatement, self, { body: [ self, alt ] }).optimize(compressor);
9737 if (aborts(self.alternative)) {
9738 var body = self.body;
9739 self.body = self.alternative;
9740 self.condition = negated_is_best ? negated : self.condition.negate(compressor);
9741 self.alternative = null;
9742 return make_node(AST_BlockStatement, self, { body: [ self, body ] }).optimize(compressor);
9744 if (self.alternative) {
9745 var body_stats = as_array(self.body);
9747 var alt_stats = as_array(self.alternative);
9768 self.body = body_stats.length > 0 ? make_node(AST_BlockStatement, self, {
9770 }) : make_node(AST_EmptyStatement, self);
9771 self.alternative = alt_stats.length > 0 ? make_node(AST_BlockStatement, self, {
9774 stats.unshift(self);
9775 return make_node(AST_BlockStatement, self, { body: stats }).optimize(compressor);
9778 if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
9779 return self;
9786 var has_finally = false, level = 0, node = compressor.self();
9879 OPT(AST_Switch, function(self, compressor) {
9880 if (!compressor.option("switches")) return self;
9881 if (!compressor.option("dead_code")) return self;
9888 for (var i = 0, len = self.body.length; i < len; i++) {
9889 branch = self.body[i];
9900 var equals = make_node(AST_Binary, self, {
9902 left: self.expression,
9922 while (++i < len) eliminate_branch(self.body[i], branch);
9941 body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
9944 branch.expression = make_sequence(self, side_effects);
9951 body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
9970 decl.push(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));
9971 if (side_effects.length) decl.push(make_node(AST_SimpleStatement, self, {
9972 body: make_sequence(self, side_effects),
9974 return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor);
9983 default_branch.body.unshift(make_node(AST_SimpleStatement, self, { body: exp }));
9989 self.body = body;
9995 if (body[0] !== default_branch && body[0] !== exact_match) return make_node(AST_If, self, {
9996 condition: make_node(AST_Binary, self, {
9998 left: self.expression,
10001 body: make_node(AST_BlockStatement, self, { body: statements }),
10005 statements.unshift(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));
10006 return make_node(AST_BlockStatement, self, { body: statements }).optimize(compressor);
10014 var node = make_node(AST_If, self, {
10015 condition: make_node(AST_Binary, self, body[0] === default_branch ? {
10017 left: self.expression,
10021 left: self.expression,
10027 if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, { body: [ node, alternative ] });
10030 return self;
10033 return node instanceof AST_Break && tw.loopcontrol_target(node) === self;
10044 tw.push(self);
10058 OPT(AST_Try, function(self, compressor) {
10059 self.body = tighten_body(self.body, compressor);
10061 if (has_declarations_only(self)
10062 && !(self.bcatch && self.bcatch.argname && self.bcatch.argname.match_symbol(function(node) {
10066 if (self.bcatch) {
10067 extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
10078 body.unshift(make_node(AST_BlockStatement, self).optimize(compressor));
10079 if (self.bfinally) {
10080 body.push(make_node(AST_BlockStatement, self.bfinally).optimize(compressor));
10082 return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
10084 if (self.bfinally && has_declarations_only(self.bfinally)) {
10085 var body = make_node(AST_BlockStatement, self.bfinally).optimize(compressor);
10086 body = self.body.concat(body);
10087 if (!self.bcatch) return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
10088 self.body = body;
10089 self.bfinally = null;
10092 return self;
10200 function varify(self, compressor) {
10201 return compressor.option("varify") && all(self.definitions, function(defn) {
10205 }) ? to_var(self, compressor.find_parent(AST_Scope)) : self;
10363 OPT(AST_Call, function(self, compressor) {
10364 var exp = self.expression;
10365 var terminated = trim_optional_chain(self, compressor);
10371 var call = self.clone();
10377 var seq = lift_sequence_in_expression(self, compressor);
10378 if (seq !== self) return seq.optimize(compressor);
10381 if (compressor.option("unused")) drop_unused_call_args(self, compressor);
10386 if (self.args.length == 1) {
10387 var first = self.args[0];
10392 for (var i = 0; i < length; i++) elements[i] = make_node(AST_Hole, self);
10393 return make_node(AST_Array, self, { elements: elements });
10397 start: self.start,
10404 return make_node(AST_Array, self, { elements: self.args });
10407 if (self.args.length == 0) return make_node(AST_Object, self, { properties: [] });
10411 if (self.args.length == 0) return make_node(AST_String, self, { value: "" });
10413 if (self.args.length == 1) return make_node(AST_Binary, self, {
10415 left: make_node(AST_String, self, { value: "" }),
10416 right: self.args[0],
10421 if (self.args.length == 0) return make_node(AST_Number, self, { value: 0 });
10423 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
10425 expression: make_node(AST_Binary, self, {
10427 left: make_node(AST_String, self, { value: "" }),
10428 right: self.args[0],
10434 if (self.args.length == 0) return make_node(AST_False, self).optimize(compressor);
10436 if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
10438 expression: make_node(AST_UnaryPrefix, self, {
10440 expression: self.args[0],
10447 if (all(self.args, function(arg) {
10452 return best_of(compressor, self, make_node(AST_RegExp, self, {
10456 AST_Node.warn("Error converting {this} [{start}]", self);
10463 if (self.args.length == 0 && !(expr.may_throw_on_access(compressor) || expr instanceof AST_Super)) {
10464 return make_node(AST_Binary, self, {
10466 left: make_node(AST_String, self, { value: "" }),
10472 if (exp.expression instanceof AST_Array && self.args.length < 2) EXIT: {
10473 var separator = self.args[0];
10477 return separator ? make_sequence(self, [
10479 make_node(AST_String, self, { value: "" }),
10480 ]).optimize(compressor) : make_node(AST_String, self, { value: "" });
10497 elements.push(make_node(AST_String, self, { value: consts.join(separator) }));
10503 if (consts.length > 0) elements.push(make_node(AST_String, self, {
10514 left: make_node(AST_String, self, { value: "" }),
10524 first = make_node(AST_String, self, { value: "" });
10538 var node = self.clone();
10542 return best_of(compressor, self, node);
10546 if (self.args.length < 2) {
10547 var node = make_node(AST_Binary, self, {
10549 left: make_node(AST_Sub, self, {
10551 property: self.args.length ? make_node(AST_Binary, self.args[0], {
10553 left: make_node(AST_Number, self, { value: 0 }),
10554 right: self.args[0],
10555 }) : make_node(AST_Number, self, { value: 0 }),
10557 right: make_node(AST_String, self, { value: "" }),
10564 if (self.args.length == 2 && self.args[1] instanceof AST_Array) {
10565 var args = self.args[1].elements.slice();
10566 args.unshift(self.args[0]);
10567 return make_node(AST_Call, self, {
10582 return (self.args.length ? make_sequence(self, [
10583 self.args[0],
10584 make_node(AST_Call, self, {
10586 args: self.args.slice(1),
10588 ]) : make_node(AST_Call, self, {
10599 var call = self.clone();
10600 call.expression = maintain_this_binding(self, exp, exp.args[0]);
10608 if (self.args.length == 0) return make_node(AST_Function, self, {
10612 if (all(self.args, function(x) {
10619 var code = "n(function(" + self.args.slice(0, -1).map(function(arg) {
10621 }).join() + "){" + self.args[self.args.length - 1].value + "})";
10640 self.args = [
10641 make_node(AST_String, self, {
10646 make_node(AST_String, self.args[self.args.length - 1], {
10650 return self;
10653 AST_Node.warn("Error parsing code passed to new Function [{start}]", self.args[self.args.length - 1]);
10662 var parent = compressor.parent(), current = compressor.self();
10668 var has_spread = !all(self.args, function(arg) {
10672 if (has_default == 1 && self.args[index] instanceof AST_Spread) has_default = 2;
10675 var arg = has_default == 1 && self.args[index];
10688 && !self.is_expr_pure(compressor)
10696 return make_sequence(self, convert_args(value)).optimize(compressor);
10710 var args = self.args.slice();
10721 if (!arg) return make_node(AST_Undefined, self);
10739 var node = make_sequence(self, exprs).optimize(compressor);
10742 if (replacing || best_of_expression(node, self) === node) {
10752 self.drop_side_effect_free = function(compressor, first_in_statement) {
10753 var self = this;
10754 var exprs = self.args.slice();
10755 exprs.unshift(self.expression);
10756 return make_sequence(self, exprs).drop_side_effect_free(compressor, first_in_statement);
10764 var node = make_sequence(self, flatten_fn()).optimize(compressor);
10774 return make_sequence(self, convert_args()).optimize(compressor);
10784 return make_node(AST_Undefined, self).optimize(compressor);
10789 return self.negate(compressor, true);
10791 return try_evaluate(compressor, self);
10801 var args = self.args.slice();
10803 if (destructured || has_spread) args = [ make_node(AST_Array, self, { elements: args }) ];
10855 args[0] = make_node(AST_Assign, self, {
10866 args.push(value || make_node(AST_Undefined, self));
10871 return self.call_only ? make_node(AST_Number, self, { value: 0 }) : make_node(AST_Undefined, self);
10878 return self.call_only ? stat.body : make_node(AST_UnaryPrefix, stat, {
10979 var end = self.args.length;
10985 return end <= begin || all(self.args.slice(begin, end), side_effects && !in_order ? function(funarg) {
11089 expressions.push(make_node(AST_Assign, self, {
11098 for (var i = self.args.length; --i >= len;) {
11099 expressions.push(self.args[i]);
11111 var value = self.args[i];
11125 value = make_node(AST_Undefined, self);
11150 expressions.push(make_node(AST_Assign, self, {
11152 left: make_node(AST_DestructuredArray, self, {
11159 right: make_node(AST_Array, self, { elements: self.args.slice() }),
11244 OPT(AST_New, function(self, compressor) {
11246 var exp = self.expression;
11253 return make_node(AST_Call, self).transform(compressor);
11257 var seq = lift_sequence_in_expression(self, compressor);
11258 if (seq !== self) return seq.optimize(compressor);
11260 if (compressor.option("unused")) drop_unused_call_args(self, compressor);
11261 return self;
11298 OPT(AST_Sequence, function(self, compressor) {
11304 self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
11305 if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
11306 return self;
11308 self.expressions = expressions;
11309 return self;
11312 if (!compressor.option("side_effects")) return self.expressions;
11315 var last = self.expressions.length - 1;
11316 self.expressions.forEach(function(expr, index) {
11330 expressions[end] = make_node(AST_UnaryPrefix, self, {
11369 OPT(AST_UnaryPostfix, function(self, compressor) {
11371 var seq = lift_sequence_in_expression(self, compressor);
11372 if (seq !== self) return seq.optimize(compressor);
11374 return try_evaluate(compressor, self);
11379 OPT(AST_UnaryPrefix, function(self, compressor) {
11380 var op = self.operator;
11381 var exp = self.expression;
11383 var seq = lift_sequence_in_expression(self, compressor);
11384 if (seq !== self) return seq.optimize(compressor);
11396 if (exp instanceof AST_Number || exp instanceof AST_Infinity) return self;
11400 if (exp.is_truthy()) return make_sequence(self, [ exp, make_node(AST_False, self) ]).optimize(compressor);
11406 self = (first ? best_of_statement : best_of_expression)(self, exp.negate(compressor, first));
11413 return make_sequence(self, [ exp, make_node(AST_True, self) ]).optimize(compressor);
11418 AST_Node.warn("Boolean expression always true [{start}]", self);
11419 var exprs = [ make_node(AST_True, self) ];
11421 return make_sequence(self, exprs).optimize(compressor);
11425 if (!exp) return make_node(AST_Undefined, self).optimize(compressor);
11426 self.expression = exp;
11427 return self;
11434 return make_node(AST_Binary, self, {
11443 return try_evaluate(compressor, self);
11466 OPT(AST_Await, function(self, compressor) {
11467 if (!compressor.option("awaits")) return self;
11469 var seq = lift_sequence_in_expression(self, compressor);
11470 if (seq !== self) return seq.optimize(compressor);
11473 var exp = self.expression;
11476 for (var level = 0, node = self, parent; parent = compressor.parent(level++); node = parent) {
11496 return self;
11499 OPT(AST_Yield, function(self, compressor) {
11500 if (!compressor.option("yields")) return self;
11502 var seq = lift_sequence_in_expression(self, compressor);
11503 if (seq !== self) return seq.optimize(compressor);
11505 var exp = self.expression;
11506 if (self.nested && exp.TYPE == "Call") {
11510 return self;
11619 function swap_chain(self, compressor) {
11620 var rhs = self.right.tail_node();
11621 if (rhs !== self.right) {
11622 var exprs = self.right.expressions.slice(0, -1);
11625 rhs.left = make_sequence(self.right, exprs);
11626 self.right = rhs;
11628 self.left = make_node(AST_Binary, self, {
11629 operator: self.operator,
11630 left: self.left,
11632 start: self.left.start,
11635 self.right = rhs.right;
11637 self.left = self.left.transform(compressor);
11638 } else if (self.operator == rhs.left.operator) {
11639 swap_chain(self.left);
11643 OPT(AST_Binary, function(self, compressor) {
11644 if (commutativeOperators[self.operator]
11645 && self.right.is_constant()
11646 && !self.left.is_constant()
11647 && !(self.left instanceof AST_Binary
11648 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
11655 var seq = self.lift_sequences(compressor);
11656 if (seq !== self) return seq.optimize(compressor);
11658 if (compressor.option("assignments") && lazy_op[self.operator]) {
11659 var lhs = extract_lhs(self.left, compressor);
11660 var right = self.right;
11668 var assign = make_node(AST_Assign, self, {
11671 right: make_node(AST_Binary, self, {
11672 operator: self.operator,
11673 left: self.left,
11689 if (compressor.option("comparisons")) switch (self.operator) {
11692 if (is_undefined(self.left, compressor) && self.right.is_defined(compressor)) {
11693 AST_Node.warn("Expression always defined [{start}]", self);
11694 return make_sequence(self, [
11695 self.right,
11696 make_node(self.operator == "===" ? AST_False : AST_True, self),
11700 if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
11701 (self.left.is_number(compressor) && self.right.is_number(compressor)) ||
11702 (self.left.is_boolean(compressor) && self.right.is_boolean(compressor)) ||
11703 repeatable(compressor, self.left) && self.left.equals(self.right)) {
11704 self.operator = self.operator.slice(0, 2);
11710 if (!is_strict_comparison && is_undefined(self.left, compressor)) {
11711 self.left = make_node(AST_Null, self.left);
11715 && self.left instanceof AST_String
11716 && self.left.value == "undefined"
11717 && self.right instanceof AST_UnaryPrefix
11718 && self.right.operator == "typeof") {
11719 var expr = self.right.expression;
11722 self.right = expr;
11723 self.left = make_node(AST_Undefined, self.left).optimize(compressor);
11724 if (self.operator.length == 2) self.operator += "=";
11728 else if (self.left instanceof AST_SymbolRef
11729 && self.right instanceof AST_SymbolRef
11730 && self.left.definition() === self.right.definition()
11731 && is_object(self.left)) {
11732 return make_node(self.operator[0] == "=" ? AST_True : AST_False, self).optimize(compressor);
11739 var left = self.left;
11741 if (left.operator != (self.operator == "&&" ? "!==" : "===")) break;
11742 if (!(self.right instanceof AST_Binary)) break;
11743 if (left.operator != self.right.operator) break;
11744 if (is_undefined(left.left, compressor) && self.right.left instanceof AST_Null
11745 || left.left instanceof AST_Null && is_undefined(self.right.left, compressor)) {
11749 if (!expr.equals(self.right.right)) break;
11751 left.left = make_node(AST_Null, self);
11759 var lhs = extract_lhs(self.left, compressor);
11760 if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
11763 if (lhs.equals(self.right)) {
11764 return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
11770 if (in_bool) switch (self.operator) {
11772 var ev = self.left.evaluate(compressor, true);
11773 if (ev && typeof ev == "string" || (ev = self.right.evaluate(compressor, true)) && typeof ev == "string") {
11774 AST_Node.warn("+ in boolean context always true [{start}]", self);
11776 if (self.left.evaluate(compressor) instanceof AST_Node) exprs.push(self.left);
11777 if (self.right.evaluate(compressor) instanceof AST_Node) exprs.push(self.right);
11779 exprs.push(make_node(AST_True, self));
11780 return make_sequence(self, exprs).optimize(compressor);
11782 self.truthy = true;
11786 if (self.left instanceof AST_String && self.left.value == "" && self.right.is_string(compressor)) {
11787 return make_node(AST_UnaryPrefix, self, {
11789 expression: self.right,
11794 if (self.left instanceof AST_String && self.left.value == "" && self.right.is_string(compressor)) {
11795 return self.right.optimize(compressor);
11799 if (compressor.option("comparisons") && self.is_boolean(compressor)) {
11801 var negated = make_node(AST_UnaryPrefix, self, {
11803 expression: self.negate(compressor),
11805 if (best_of(compressor, self, negated) === negated) return negated;
11807 switch (self.operator) {
11812 if (compressor.option("conditionals") && lazy_op[self.operator]) {
11813 if (self.left instanceof AST_Binary && self.operator == self.left.operator) {
11814 var before = make_node(AST_Binary, self, {
11815 operator: self.operator,
11816 left: self.left.right,
11817 right: self.right,
11821 self.left = self.left.left;
11822 self.right = after;
11827 var rhs = self.right.tail_node();
11828 if (rhs instanceof AST_Binary && self.operator == rhs.operator) swap_chain(self, compressor);
11830 if (compressor.option("strings") && self.operator == "+") {
11832 if (self.right instanceof AST_String
11833 && self.right.value == ""
11834 && self.left.is_string(compressor)) {
11835 return self.left.optimize(compressor);
11838 if (self.left instanceof AST_String
11839 && self.left.value == ""
11840 && self.right.is_string(compressor)) {
11841 return self.right.optimize(compressor);
11844 if (self.left instanceof AST_Binary
11845 && self.left.operator == "+"
11846 && self.left.left instanceof AST_String
11847 && self.left.left.value == ""
11848 && self.right.is_string(compressor)
11849 && (self.left.right.is_constant() || !self.right.has_side_effects(compressor))) {
11850 self.left = self.left.right;
11851 return self.optimize(compressor);
11855 var rhs = self.right.tail_node();
11857 && self.operator == rhs.operator
11858 && (self.left.is_string(compressor) && rhs.is_string(compressor)
11860 && (self.left.is_constant() || !rhs.right.has_side_effects(compressor)))) {
11861 swap_chain(self, compressor);
11866 switch (self.operator) {
11868 var ll = fuzzy_eval(compressor, self.left);
11870 AST_Node.warn("Condition left of && always false [{start}]", self);
11871 return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
11873 AST_Node.warn("Condition left of && always true [{start}]", self);
11874 return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
11876 if (!self.right.evaluate(compressor, true)) {
11877 if (in_bool && !(self.right.evaluate(compressor) instanceof AST_Node)) {
11878 AST_Node.warn("Boolean && always false [{start}]", self);
11879 return make_sequence(self, [ self.left, make_node(AST_False, self) ]).optimize(compressor);
11880 } else self.falsy = true;
11881 } else if ((in_bool || parent.operator == "&&" && parent.left === compressor.self())
11882 && !(self.right.evaluate(compressor) instanceof AST_Node)) {
11883 AST_Node.warn("Dropping side-effect-free && [{start}]", self);
11884 return self.left.optimize(compressor);
11887 if (self.left.operator == "||") {
11888 var lr = fuzzy_eval(compressor, self.left.right);
11889 if (!lr) return make_node(AST_Conditional, self, {
11890 condition: self.left.left,
11891 consequent: self.right,
11892 alternative: self.left.right,
11899 var ll = fuzzy_eval(compressor, self.left, nullish);
11902 operator: self.operator,
11904 start: self.start,
11906 return make_sequence(self, [ self.left, self.right ]).optimize(compressor);
11909 operator: self.operator,
11911 start: self.start,
11913 return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);
11916 if (!nullish && (rr = self.right.evaluate(compressor, true)) && !(rr instanceof AST_Node)) {
11917 if (in_bool && !(self.right.evaluate(compressor) instanceof AST_Node)) {
11918 AST_Node.warn("Boolean || always true [{start}]", self);
11919 return make_sequence(self, [ self.left, make_node(AST_True, self) ]).optimize(compressor);
11920 } else self.truthy = true;
11921 } else if ((in_bool || parent.operator == "||" && parent.left === compressor.self())
11922 && !self.right.evaluate(compressor)) {
11923 AST_Node.warn("Dropping side-effect-free {operator} [{start}]", self);
11924 return self.left.optimize(compressor);
11927 if (!nullish && self.left.operator == "&&") {
11928 var lr = fuzzy_eval(compressor, self.left.right);
11929 if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {
11930 condition: self.left.left,
11931 consequent: self.left.right,
11932 alternative: self.right,
11938 if (self.left instanceof AST_Constant
11939 && self.right instanceof AST_Binary
11940 && self.right.operator == "+"
11941 && self.right.left instanceof AST_Constant
11942 && self.right.is_string(compressor)) {
11943 self = make_node(AST_Binary, self, {
11945 left: make_node(AST_String, self.left, {
11946 value: "" + self.left.value + self.right.left.value,
11947 start: self.left.start,
11948 end: self.right.left.end,
11950 right: self.right.right,
11954 if (self.right instanceof AST_Constant
11955 && self.left instanceof AST_Binary
11956 && self.left.operator == "+"
11957 && self.left.right instanceof AST_Constant
11958 && self.left.is_string(compressor)) {
11959 self = make_node(AST_Binary, self, {
11961 left: self.left.left,
11962 right: make_node(AST_String, self.right, {
11963 value: "" + self.left.right.value + self.right.value,
11964 start: self.left.right.start,
11965 end: self.right.end,
11970 if (self.right instanceof AST_UnaryPrefix
11971 && self.right.operator == "-"
11972 && self.left.is_number(compressor)) {
11973 self = make_node(AST_Binary, self, {
11975 left: self.left,
11976 right: self.right.expression,
11981 if (self.left instanceof AST_UnaryPrefix
11982 && self.left.operator == "-"
11984 && self.right.is_number(compressor)) {
11985 self = make_node(AST_Binary, self, {
11987 left: self.right,
11988 right: self.left.expression,
11994 && self.left instanceof AST_Binary
11995 && PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]
11996 && self.right.is_constant()
11997 && (self.right.is_boolean(compressor) || self.right.is_number(compressor))
11998 && self.left.is_number(compressor)
11999 && !self.left.right.is_constant()
12000 && (self.left.left.is_boolean(compressor) || self.left.left.is_number(compressor))) {
12001 self = make_node(AST_Binary, self, {
12002 operator: self.left.operator,
12003 left: make_node(AST_Binary, self, {
12004 operator: self.operator,
12005 left: self.right,
12006 right: self.left.left,
12008 right: self.left.right,
12014 if (self.right instanceof AST_UnaryPrefix
12015 && self.right.operator == "-"
12016 && self.left.is_number(compressor)
12017 && self.right.expression.is_number(compressor)) {
12018 self = make_node(AST_Binary, self, {
12020 left: self.left,
12021 right: self.right.expression,
12030 if (self.operator != "+") [ "left", "right" ].forEach(function(operand) {
12031 var node = self[operand];
12035 self[operand] = exp;
12043 if (self.operator != "-"
12044 && self.operator != "/"
12045 && (self.left.is_boolean(compressor) || self.left.is_number(compressor))
12046 && (self.right.is_boolean(compressor) || self.right.is_number(compressor))
12048 && !(self.left instanceof AST_Binary
12049 && self.left.operator != self.operator
12050 && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
12051 self = best_of(compressor, self, make_node(AST_Binary, self, {
12052 operator: self.operator,
12053 left: self.right,
12054 right: self.left,
12055 }), self.right instanceof AST_Constant && !(self.left instanceof AST_Constant));
12057 if (!associative || !self.is_number(compressor)) break;
12059 if (self.right instanceof AST_Binary
12060 && self.right.operator != "%"
12061 && PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]
12062 && self.right.is_number(compressor)
12063 && (self.operator != "+"
12064 || self.right.left.is_boolean(compressor)
12065 || self.right.left.is_number(compressor))
12066 && (self.operator != "-" || !self.left.is_negative_zero())
12067 && (self.right.left.is_constant_expression()
12068 || !self.right.right.has_side_effects(compressor))
12069 && !is_modify_array(self.right.right)) {
12070 self = make_node(AST_Binary, self, {
12071 operator: align(self.operator, self.right.operator),
12072 left: make_node(AST_Binary, self.left, {
12073 operator: self.operator,
12074 left: self.left,
12075 right: self.right.left,
12076 start: self.left.start,
12077 end: self.right.left.end,
12079 right: self.right.right,
12081 if (self.operator == "+"
12082 && !self.right.is_boolean(compressor)
12083 && !self.right.is_number(compressor)) {
12084 self.right = make_node(AST_UnaryPrefix, self.right, {
12086 expression: self.right,
12092 if (self.right instanceof AST_Constant
12093 && self.left instanceof AST_Binary
12094 && self.left.operator != "%"
12095 && PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]
12096 && self.left.is_number(compressor)) {
12097 if (self.left.left instanceof AST_Constant) {
12098 var lhs = make_binary(self.operator, self.left.left, self.right, {
12099 start: self.left.left.start,
12100 end: self.right.end,
12102 self = make_binary(self.left.operator, try_evaluate(compressor, lhs), self.left.right, self);
12103 } else if (self.left.right instanceof AST_Constant) {
12104 var op = align(self.left.operator, self.operator);
12105 var rhs = try_evaluate(compressor, make_binary(op, self.left.right, self.right, self.left));
12107 && !(self.left.operator == "-"
12108 && self.right.value != 0
12110 && self.left.left.is_negative_zero())) {
12111 self = make_binary(self.left.operator, self.left.left, rhs, self);
12117 if (is_lambda(self.right)) return make_sequence(self, [
12118 self,
12119 make_node(AST_False, self),
12124 if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {
12127 if (self.left.value == 0) {
12128 if (self.right.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, {
12130 expression: self.right,
12132 if (self.right.is_number(compressor) && !self.right.is_negative_zero()) return self.right;
12137 if (self.left.value == 1) return make_node(AST_UnaryPrefix, self, {
12139 expression: self.right,
12143 if (self.right instanceof AST_Number && !self.left.is_constant()) switch (self.operator) {
12146 if (self.right.value == 0) {
12147 if (self.left.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, {
12149 expression: self.left,
12151 if (self.left.is_number(compressor) && !self.left.is_negative_zero()) return self.left;
12156 if (self.right.value == 0) return make_node(AST_UnaryPrefix, self, {
12158 expression: self.left,
12163 if (self.right.value == 1) return make_node(AST_UnaryPrefix, self, {
12165 expression: self.left,
12171 if (compressor.option("typeofs")) switch (self.operator) {
12173 mark_locally_defined(self.left, self.right, null);
12176 mark_locally_defined(self.left, null, self.right);
12180 var indexRight = is_indexFn(self.right);
12183 && (self.operator == "==" || self.operator == "!=")
12184 && self.left instanceof AST_Number
12185 && self.left.value == 0) {
12186 return (self.operator == "==" ? make_node(AST_UnaryPrefix, self, {
12188 expression: self.right,
12189 }) : self.right).optimize(compressor);
12191 var indexLeft = is_indexFn(self.left);
12193 var node = make_node(AST_UnaryPrefix, self, {
12195 expression: make_node(AST_UnaryPrefix, self, {
12197 expression: indexLeft ? self.left : self.right,
12200 switch (self.operator) {
12205 node = make_node(AST_UnaryPrefix, self, {
12214 return try_evaluate(compressor, self);
12271 switch (self.operator) {
12274 return indexRight && self.left instanceof AST_Number && self.left.value == 0;
12277 if (indexLeft && self.right instanceof AST_Number && self.right.value == 0) return true;
12284 return self.left instanceof AST_Number && self.left.value == -1
12285 || self.left instanceof AST_UnaryPrefix && self.left.operator == "-"
12286 && self.left.expression instanceof AST_Number && self.left.expression.value == 1;
12291 return self.left.is_constant()
12292 || self.right.is_constant()
12293 || !self.left.has_side_effects(compressor)
12294 && !self.right.has_side_effects(compressor);
12299 if (op) self.operator = op;
12300 var tmp = self.left;
12301 self.left = self.right;
12302 self.right = tmp;
12307 OPT(AST_SymbolExport, function(self) {
12308 return self;
12312 var level = 0, node = compressor.self();
12326 OPT(AST_SymbolRef, function(self, compressor) {
12328 && is_undeclared_ref(self)
12329 // testing against `self.scope.uses_with` is an optimization
12330 && !(self.scope.resolve().uses_with && compressor.find_parent(AST_With))) {
12331 switch (self.name) {
12333 return make_node(AST_Undefined, self).optimize(compressor);
12335 return make_node(AST_NaN, self).optimize(compressor);
12337 return make_node(AST_Infinity, self).optimize(compressor);
12341 if (compressor.option("reduce_vars") && is_lhs(compressor.self(), parent) !== compressor.self()) {
12342 var def = self.definition();
12343 var fixed = self.fixed_value();
12347 if ((def.scope !== self.scope.resolve(true) || def.in_loop)
12356 } else if (fixed.parent_scope !== self.scope || is_funarg(def)) {
12359 } else if ((single_use = fixed.is_constant_expression(self.scope)) == "f") {
12360 var scope = self.scope;
12375 if (single_use) fixed.parent_scope = self.scope;
12391 var scope = self.scope;
12472 if (fixed && (state = self.fixed || def.fixed).should_replace !== false) {
12515 return self;
12518 var scope = self.scope;
12553 OPT(AST_Template, function(self, compressor) {
12554 if (!compressor.option("templates")) return self;
12555 var tag = self.tag;
12559 for (var i = 0, status; i < self.strings.length; i++) {
12560 var str = self.strings[i];
12566 var node = self.expressions[i - 1];
12583 if (strs[strs.length - 1] == "") return make_node(AST_Binary, self, {
12585 left: make_node(AST_Template, self, {
12592 var left = make_node(AST_Binary, self, {
12594 left: make_node(AST_String, self, { value: "" }),
12598 left = make_node(AST_Binary, self, {
12604 return best_of(compressor, self, make_node(AST_Binary, self, {
12607 right: make_node(AST_Template, self, {
12614 self.expressions = exprs;
12615 self.strings = strs;
12617 return try_evaluate(compressor, self);
12635 function is_atomic(lhs, self) {
12636 return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
12639 OPT(AST_Undefined, function(self, compressor) {
12643 var ref = make_node(AST_SymbolRef, self, {
12652 var lhs = is_lhs(compressor.self(), compressor.parent());
12653 if (lhs && is_atomic(lhs, self)) return self;
12654 return make_node(AST_UnaryPrefix, self, {
12656 expression: make_node(AST_Number, self, { value: 0 }),
12660 OPT(AST_Infinity, function(self, compressor) {
12661 var lhs = is_lhs(compressor.self(), compressor.parent());
12662 if (lhs && is_atomic(lhs, self)) return self;
12664 return self;
12666 return make_node(AST_Binary, self, {
12668 left: make_node(AST_Number, self, { value: 1 }),
12669 right: make_node(AST_Number, self, { value: 0 }),
12673 OPT(AST_NaN, function(self, compressor) {
12674 var lhs = is_lhs(compressor.self(), compressor.parent());
12675 if (lhs && is_atomic(lhs, self)) return self;
12676 if (!lhs && !find_scope(compressor).find_variable("NaN")) return self;
12677 return make_node(AST_Binary, self, {
12679 left: make_node(AST_Number, self, { value: 0 }),
12680 right: make_node(AST_Number, self, { value: 0 }),
12684 function is_reachable(self, defs) {
12692 if (node instanceof AST_Lambda && node !== self) {
12701 self.walk(scan_scope);
12707 OPT(AST_Assign, function(self, compressor) {
12709 if (self.left instanceof AST_PropAccess) {
12710 if (self.operator == "=") {
12711 if (self.redundant) {
12712 var exprs = [ self.left.expression ];
12713 if (self.left instanceof AST_Sub) exprs.push(self.left.property);
12714 exprs.push(self.right);
12715 return make_sequence(self, exprs).optimize(compressor);
12717 if (self.left.equals(self.right) && !self.left.has_side_effects(compressor)) {
12718 return self.right;
12720 var exp = self.left.expression;
12725 return self.left instanceof AST_Dot ? self.right : make_sequence(self, [
12726 self.left.property,
12727 self.right
12731 } else if (self.left instanceof AST_SymbolRef && can_drop_symbol(self.left, compressor)) {
12733 if (self.operator == "=" && self.left.equals(self.right)
12735 return self.right;
12737 if (self.left.is_immutable()) return strip_assignment();
12738 var def = self.left.definition();
12742 parent = compressor.self();
12783 var seq = self.lift_sequences(compressor);
12784 if (seq !== self) return seq.optimize(compressor);
12787 if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
12789 if (self.right.left instanceof AST_SymbolRef
12790 && self.right.left.name == self.left.name
12791 && ASSIGN_OPS[self.right.operator]) {
12793 return make_compound(self.right.right);
12795 if (self.right.right instanceof AST_SymbolRef
12796 && self.right.right.name == self.left.name
12797 && ASSIGN_OPS_COMMUTATIVE[self.right.operator]
12798 && !self.right.left.has_side_effects(compressor)) {
12800 return make_compound(self.right.left);
12803 if ((self.operator == "-=" || self.operator == "+="
12804 && (self.left.is_boolean(compressor) || self.left.is_number(compressor)))
12805 && self.right instanceof AST_Number
12806 && self.right.value == 1) {
12807 var op = self.operator.slice(0, -1);
12808 return make_node(AST_UnaryPrefix, self, {
12810 expression: self.left,
12814 return try_evaluate(compressor, self);
12856 var right = self.right;
12857 self.right = make_node(AST_Null, right);
12859 self.right = right;
12864 var fixed = self.left.fixed;
12868 return make_node(AST_Assign, self, {
12869 operator: self.right.operator + "=",
12870 left: self.left,
12877 return (self.operator != "=" ? make_node(AST_Binary, self, {
12878 operator: self.operator.slice(0, -1),
12879 left: self.left,
12880 right: self.right,
12881 }) : maintain_this_binding(compressor.parent(), self, self.right)).optimize(compressor);
12885 OPT(AST_Conditional, function(self, compressor) {
12886 if (compressor.option("sequences") && self.condition instanceof AST_Sequence) {
12887 var expressions = self.condition.expressions.slice();
12888 var node = self.clone();
12891 return make_sequence(self, expressions).optimize(compressor);
12893 if (!compressor.option("conditionals")) return self;
12894 var condition = self.condition;
12900 AST_Node.warn("Condition always false [{start}]", self);
12901 return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);
12903 AST_Node.warn("Condition always true [{start}]", self);
12904 return make_sequence(self, [ self.condition, self.consequent ]).optimize(compressor);
12909 self = make_node(AST_Conditional, self, {
12911 consequent: self.alternative,
12912 alternative: self.consequent,
12915 condition = self.condition;
12917 var consequent = self.consequent;
12918 var alternative = self.alternative;
12922 if (cond_lhs.equals(consequent)) return make_node(AST_Binary, self, {
12928 if (cond_lhs.equals(alternative)) return make_node(AST_Binary, self, {
12950 return make_node(AST_Assign, self, {
12953 right: make_node(AST_Conditional, self, {
12964 if (seq_tail.equals(alt_tail)) return make_sequence(self, consequent.equals(alternative) ? [
12968 make_node(AST_Conditional, self, {
12990 node.args[arg_index] = arg instanceof AST_Spread ? make_node(AST_Spread, self, {
12991 expression: make_node(AST_Conditional, self, {
12996 }) : make_node(AST_Conditional, self, {
13006 return make_node(AST_Conditional, self, {
13007 condition: make_node(AST_Binary, self, {
13019 return make_node(AST_Conditional, self, {
13020 condition: make_node(AST_Binary, self, {
13032 return make_node(AST_Conditional, self, {
13033 condition: make_node(AST_Binary, self, {
13045 return make_node(AST_Conditional, self, {
13046 condition: make_node(AST_Binary, self, {
13059 return make_node(AST_Binary, self, {
13061 left: make_node(AST_Binary, self, {
13073 return make_node(AST_Binary, self, {
13075 left: make_node(AST_Binary, self, {
13087 return make_node(AST_Binary, self, {
13089 left: make_node(AST_Binary, self, {
13101 return make_node(AST_Binary, self, {
13103 left: make_node(AST_Binary, self, {
13116 return make_node(AST_Binary, self, {
13126 return make_node(AST_Binary, self, {
13133 if (is_true(alternative)) return make_node(AST_Binary, self, {
13139 if (is_false(alternative)) return make_node(AST_Binary, self, {
13145 return self;
13226 if (!is_tail_equivalent(seq_tail, alt_tail)) return !top && make_node(AST_Conditional, self, {
13261 OPT(AST_Boolean, function(self, compressor) {
13262 if (!compressor.option("booleans")) return self;
13263 if (compressor.in_boolean_context()) return make_node(AST_Number, self, { value: +self.value });
13268 value: self.value,
13271 return make_node(AST_Number, self, { value: +self.value });
13273 return make_node(AST_UnaryPrefix, self, {
13275 expression: make_node(AST_Number, self, { value: 1 - self.value }),
13279 OPT(AST_Spread, function(self, compressor) {
13280 var exp = self.expression;
13286 return self;
13293 if (parent.expression !== compressor.self()) return true;
13301 OPT(AST_Sub, function(self, compressor) {
13302 var expr = self.expression;
13303 var prop = self.property;
13304 var terminated = trim_optional_chain(self, compressor);
13319 prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
13323 return make_node(AST_Dot, self, {
13324 optional: self.optional,
13333 var assigned = is_lhs(compressor.self(), parent);
13388 if (assigned) return self;
13391 && !(parent instanceof AST_ForEnumeration && parent.init === self)) {
13392 var seq = lift_sequence_in_expression(self, compressor);
13393 if (seq !== self) return seq.optimize(compressor);
13396 var sub = self.flatten_object(property, compressor);
13398 expr = self.expression = sub.expression;
13399 prop = self.property = sub.property;
13436 return make_sequence(self, values).optimize(compressor);
13438 return make_node(AST_Sub, self, {
13444 return try_evaluate(compressor, self);
13465 var self = this;
13466 self.walk(new TreeWalker(function(node) {
13469 if (node !== self && node instanceof AST_Scope && !is_arrow(node)) return true;
13483 var self = this;
13484 self.walk(new TreeWalker(function(node) {
13487 if (node !== self && node instanceof AST_Scope && !is_arrow(node)) return true;
13504 var self = this;
13505 var expr = self.expression;
13529 || (call = compressor.parent()) instanceof AST_Call && call.expression === self) {
13538 return make_node(AST_Sub, self, {
13540 property: make_node(AST_Number, self, { value: i }),
13545 OPT(AST_Dot, function(self, compressor) {
13546 if (self.property == "arguments" || self.property == "caller") {
13547 AST_Node.warn("Function.prototype.{property} not supported [{start}]", self);
13550 if (is_lhs(compressor.self(), parent)) return self;
13551 var terminated = trim_optional_chain(self, compressor);
13555 && !(parent instanceof AST_ForEnumeration && parent.init === self)) {
13556 var seq = lift_sequence_in_expression(self, compressor);
13557 if (seq !== self) return seq.optimize(compressor);
13560 && self.expression instanceof AST_Dot
13561 && self.expression.property == "prototype") {
13562 var exp = self.expression.expression;
13565 self.expression = make_node(AST_Array, self.expression, { elements: [] });
13568 self.expression = make_node(AST_Function, self.expression, {
13574 self.expression = make_node(AST_Number, self.expression, { value: 0 });
13577 self.expression = make_node(AST_Object, self.expression, { properties: [] });
13580 self.expression = make_node(AST_RegExp, self.expression, { value: /t/ });
13583 self.expression = make_node(AST_String, self.expression, { value: "" });
13587 var sub = self.flatten_object(self.property, compressor);
13589 return try_evaluate(compressor, self);
13592 OPT(AST_DestructuredArray, function(self, compressor) {
13593 if (compressor.option("rests") && self.rest instanceof AST_DestructuredArray) {
13594 return make_node(AST_DestructuredArray, self, {
13595 elements: self.elements.concat(self.rest.elements),
13596 rest: self.rest.rest,
13599 return self;
13602 OPT(AST_DestructuredKeyVal, function(self, compressor) {
13604 var key = self.key;
13607 if (key !== self.key) self.key = "" + key;
13610 return self;
13613 OPT(AST_Object, function(self, compressor) {
13614 if (!compressor.option("objects")) return self;
13622 self.properties.forEach(function(prop) {
13653 if (!changed) return self;
13660 return make_node(AST_Object, self, { properties: values });
13673 values.push(props.length == 1 ? props[0] : make_node(AST_ObjectKeyVal, self, {
13675 value: make_sequence(self, props.map(function(prop) {
13771 var self = this;
13772 var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, true);
13778 node.value = make_node(AST_Await, self, {
13782 return aborts(inlined) ? inlined : make_node(AST_BlockStatement, self, {
13783 body: [ inlined, make_node(AST_SimpleStatement, self, {
13784 body: make_node(AST_Await, self, { expression: make_node(AST_Number, self, { value: 0 })}),
13790 var self = this;
13791 var op = self.operator;
13793 var inlined = self.right.try_inline(compressor, scope, no_return, in_loop, in_await);
13795 return make_node(AST_If, self, {
13796 condition: make_condition(self.left),
13798 alternative: no_return ? null : make_node(AST_Return, self, {
13799 value: make_node(AST_Undefined, self).transform(compressor),
13810 return make_node(AST_Binary, self, {
13812 left: make_node(AST_Null, self),
14040 var self = this;
14041 var body = self.consequent.try_inline(compressor, scope, no_return, in_loop, in_await);
14042 var alt = self.alternative.try_inline(compressor, scope, no_return, in_loop, in_await);
14044 return make_node(AST_If, self, {
14045 condition: self.condition,
14046 body: body || make_body(self.consequent),
14047 alternative: alt || make_body(self.alternative),
14168 var self = this;
14169 var op = self.operator;
14172 var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, in_await);
14178 node.value = make_node(AST_UnaryPrefix, self, {
14223 OPT(AST_Return, function(self, compressor) {
14224 var value = self.value;
14228 self.value = null;
14230 return self;
14234 var self = this;
14235 if (self._optimized) return self;
14236 if (compressor.has_directive("use asm")) return self;
14237 var opt = optimizer(self, compressor);