diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2021-02-01 09:20:13 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-01 17:20:13 +0800 |
commit | ba6e29d6fd8df2434cb372b94c7aaccb68bc272f (patch) | |
tree | 90502d564901f98168ce35538cdacbb1b11c5da0 /lib/compress.js | |
parent | d4685640a00a0c998041c96ec197e613bd67b7b3 (diff) | |
download | tracifyjs-ba6e29d6fd8df2434cb372b94c7aaccb68bc272f.tar.gz tracifyjs-ba6e29d6fd8df2434cb372b94c7aaccb68bc272f.zip |
introduce `templates` (#4603)
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 83 |
1 files changed, 70 insertions, 13 deletions
diff --git a/lib/compress.js b/lib/compress.js index 700f3748..f894a6cb 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -91,6 +91,7 @@ function Compressor(options, false_by_default) { spreads : !false_by_default, strings : !false_by_default, switches : !false_by_default, + templates : !false_by_default, top_retain : null, toplevel : !!(options && options["top_retain"]), typeofs : !false_by_default, @@ -3689,6 +3690,9 @@ merge(Compressor.prototype, { delete this.is_string; return result; }); + def(AST_Template, function(compressor) { + return !this.tag || is_raw_tag(compressor, this.tag); + }); def(AST_UnaryPrefix, function() { return this.operator == "typeof"; }); @@ -4298,6 +4302,16 @@ merge(Compressor.prototype, { } return this; }); + function eval_all(nodes, compressor, ignore_side_effects, cached, depth) { + var values = []; + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var value = node._eval(compressor, ignore_side_effects, cached, depth); + if (node === value) return; + values.push(value); + } + return values; + } def(AST_Call, function(compressor, ignore_side_effects, cached, depth) { var exp = this.expression; var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp; @@ -4305,7 +4319,7 @@ merge(Compressor.prototype, { if (fn.evaluating) return this; if (fn.name && fn.name.definition().recursive_refs > 0) return this; if (this.is_expr_pure(compressor)) return this; - var args = eval_args(this.args); + var args = eval_all(this.args, compressor, ignore_side_effects, cached, depth); if (!all(fn.argnames, function(sym, index) { if (sym instanceof AST_DefaultValue) { if (!args) return false; @@ -4380,7 +4394,7 @@ merge(Compressor.prototype, { if (!native_fn || !native_fn[key]) return this; if (val instanceof RegExp && val.global && !(e instanceof AST_RegExp)) return this; } - var args = eval_args(this.args); + var args = eval_all(this.args, compressor, ignore_side_effects, cached, depth); if (!args) return this; if (key == "replace" && typeof args[1] == "function") return this; try { @@ -4397,19 +4411,35 @@ merge(Compressor.prototype, { } } return this; + }); + def(AST_New, return_this); + def(AST_Template, function(compressor, ignore_side_effects, cached, depth) { + if (!compressor.option("templates")) return this; + if (this.tag) { + if (!is_raw_tag(compressor, this.tag)) return this; + decode = function(str) { + return str; + }; + } + var exprs = eval_all(this.expressions, compressor, ignore_side_effects, cached, depth); + if (!exprs) return this; + var ret = decode(this.strings[0]); + var malformed = false; + for (var i = 0; i < exprs.length; i++) { + ret += exprs[i] + decode(this.strings[i + 1]); + } + if (!malformed) return ret; + this._eval = return_this; + return this; - function eval_args(args) { - var values = []; - for (var i = 0; i < args.length; i++) { - var arg = args[i]; - var value = arg._eval(compressor, ignore_side_effects, cached, depth); - if (arg === value) return; - values.push(value); - } - return values; + function decode(str) { + return str.replace(/\\(u[0-9a-fA-F]{4}|u\{[0-9a-fA-F]+\}|x[0-9a-fA-F]{2}|[0-9]+|[\s\S])/g, function(match, seq) { + var s = decode_escape_sequence(seq); + if (typeof s != "string") malformed = true; + return s; + }); } }); - def(AST_New, return_this); })(function(node, func) { node.DEFMETHOD("_eval", func); }); @@ -4664,7 +4694,7 @@ merge(Compressor.prototype, { return !this.is_declared(compressor) || !can_drop_symbol(this); }); def(AST_Template, function(compressor) { - return any(this.expressions, compressor); + return this.tag && !is_raw_tag(compressor, this.tag) || any(this.expressions, compressor); }); def(AST_This, return_false); def(AST_Try, function(compressor) { @@ -7019,6 +7049,7 @@ merge(Compressor.prototype, { return this.is_declared(compressor) && can_drop_symbol(this) ? null : this; }); def(AST_Template, function(compressor, first_in_statement) { + if (this.tag && !is_raw_tag(compressor, this.tag)) return this; var expressions = this.expressions; if (expressions.length == 0) return null; return make_sequence(this, expressions).drop_side_effect_free(compressor, first_in_statement); @@ -9907,6 +9938,32 @@ merge(Compressor.prototype, { } }); + function is_raw_tag(compressor, tag) { + return compressor.option("unsafe") + && tag instanceof AST_Dot + && tag.property == "raw" + && is_undeclared_ref(tag.expression) + && tag.expression.name == "String"; + } + + OPT(AST_Template, function(self, compressor) { + if (!compressor.option("templates")) return self; + if (!self.tag || is_raw_tag(compressor, self.tag)) { + var exprs = self.expressions; + var strs = self.strings; + for (var i = exprs.length; --i >= 0;) { + var node = exprs[i]; + var ev = node.evaluate(compressor); + if (ev === node) continue; + ev = "" + ev; + if (ev.length > node.print_to_string().length + 3) continue; + exprs.splice(i, 1); + strs.splice(i, 2, strs[i] + ev + strs[i + 1]); + } + } + return try_evaluate(compressor, self); + }); + function is_atomic(lhs, self) { return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE; } |