| | |
| | | return value; |
| | | }); |
| | | |
| | | def_eval(AST_Chain, function (compressor, depth) { |
| | | const evaluated = this.expression._eval(compressor, depth, /*ast_chain=*/true); |
| | | return evaluated === nullish |
| | | ? undefined |
| | | : evaluated === this.expression |
| | | ? this |
| | | : evaluated; |
| | | }); |
| | | |
| | | const global_objs = { Array, Math, Number, Object, String }; |
| | | |
| | | const regexp_flags = new Set([ |
| | |
| | | "unicode", |
| | | ]); |
| | | |
| | | def_eval(AST_PropAccess, function (compressor, depth) { |
| | | let obj = this.expression._eval(compressor, depth + 1); |
| | | if (obj === nullish || (this.optional && obj == null)) return nullish; |
| | | def_eval(AST_PropAccess, function (compressor, depth, ast_chain) { |
| | | let obj = (ast_chain || this.property === "length" || compressor.option("unsafe")) |
| | | && this.expression._eval(compressor, depth + 1, ast_chain); |
| | | |
| | | if (ast_chain) { |
| | | if (obj === nullish || (this.optional && obj == null)) return nullish; |
| | | } |
| | | |
| | | // `.length` of strings and arrays is always safe |
| | | if (this.property === "length") { |
| | |
| | | return this; |
| | | }); |
| | | |
| | | def_eval(AST_Chain, function (compressor, depth) { |
| | | const evaluated = this.expression._eval(compressor, depth); |
| | | return evaluated === nullish |
| | | ? undefined |
| | | : evaluated === this.expression |
| | | ? this |
| | | : evaluated; |
| | | }); |
| | | |
| | | def_eval(AST_Call, function (compressor, depth) { |
| | | def_eval(AST_Call, function (compressor, depth, ast_chain) { |
| | | var exp = this.expression; |
| | | |
| | | const callee = exp._eval(compressor, depth); |
| | | if (callee === nullish || (this.optional && callee == null)) return nullish; |
| | | if (ast_chain) { |
| | | const callee = exp._eval(compressor, depth, ast_chain); |
| | | if (callee === nullish || (this.optional && callee == null)) return nullish; |
| | | } |
| | | |
| | | if (compressor.option("unsafe") && exp instanceof AST_PropAccess) { |
| | | var key = exp.property; |
| | | if (key instanceof AST_Node) { |
| | | key = key._eval(compressor, depth); |
| | | if (key === exp.property) |
| | | if (typeof key !== "string" && typeof key !== "number") |
| | | return this; |
| | | } |
| | | var val; |
| | |
| | | if (!is_pure_native_fn(e.name, key)) return this; |
| | | val = global_objs[e.name]; |
| | | } else { |
| | | val = e._eval(compressor, depth + 1); |
| | | val = e._eval(compressor, depth + 1, /* don't pass ast_chain (exponential work) */); |
| | | |
| | | if (val === e || !val) |
| | | return this; |
| | | if (!is_pure_native_method(val.constructor.name, key)) |