From 31a9b05c9642d8b402611d49ea23a6c2902cf374 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Tue, 16 Feb 2016 18:15:59 +0800 Subject: [PATCH] Preserve ThisBinding in conditionals & collapse_vars Fixes #973 --- lib/compress.js | 39 ++++++++++++++++------------ test/compress/issue-782.js | 6 ++--- test/compress/issue-973.js | 52 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 test/compress/issue-973.js diff --git a/lib/compress.js b/lib/compress.js index 6fdf8f2d..16dc90f5 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -176,6 +176,21 @@ merge(Compressor.prototype, { } }; + // we shouldn't compress (1,func)(something) to + // func(something) because that changes the meaning of + // the func (becomes lexical instead of global). + function maintain_this_binding(parent, orig, val) { + if (parent instanceof AST_Call && parent.expression === orig && val instanceof AST_PropAccess) { + return make_node(AST_Seq, orig, { + car: make_node(AST_Number, orig, { + value: 0 + }), + cdr: val + }); + } + return val; + } + function as_statement_array(thing) { if (thing === null) return []; if (thing instanceof AST_BlockStatement) return thing.body; @@ -366,7 +381,7 @@ merge(Compressor.prototype, { if (is_lvalue(node, parent)) return node; // Remove var definition and return its value to the TreeTransformer to replace. - var value = var_decl.value; + var value = maintain_this_binding(parent, node, var_decl.value); var_decl.value = null; var_defs.splice(var_defs_index, 1); @@ -2108,13 +2123,7 @@ merge(Compressor.prototype, { if (!compressor.option("side_effects")) return self; if (!self.car.has_side_effects(compressor)) { - // we shouldn't compress (1,func)(something) to - // func(something) because that changes the meaning of - // the func (becomes lexical instead of global). - var p = compressor.parent(); - if (!(p instanceof AST_Call && p.expression === self)) { - return self.cdr; - } + return maintain_this_binding(compressor.parent(), self, self.cdr); } if (compressor.option("cascade")) { if (self.car instanceof AST_Assign @@ -2304,11 +2313,10 @@ merge(Compressor.prototype, { if (ll.length > 1) { if (ll[1]) { compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start); - var rr = self.right.evaluate(compressor); - return rr[0]; + return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[0]); } else { compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start); - return ll[0]; + return maintain_this_binding(compressor.parent(), self, ll[0]); } } } @@ -2317,11 +2325,10 @@ merge(Compressor.prototype, { if (ll.length > 1) { if (ll[1]) { compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start); - return ll[0]; + return maintain_this_binding(compressor.parent(), self, ll[0]); } else { compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start); - var rr = self.right.evaluate(compressor); - return rr[0]; + return maintain_this_binding(compressor.parent(), self, self.right.evaluate(compressor)[0]); } } } @@ -2546,10 +2553,10 @@ merge(Compressor.prototype, { if (cond.length > 1) { if (cond[1]) { compressor.warn("Condition always true [{file}:{line},{col}]", self.start); - return self.consequent; + return maintain_this_binding(compressor.parent(), self, self.consequent); } else { compressor.warn("Condition always false [{file}:{line},{col}]", self.start); - return self.alternative; + return maintain_this_binding(compressor.parent(), self, self.alternative); } } var negated = cond[0].negate(compressor); diff --git a/test/compress/issue-782.js b/test/compress/issue-782.js index cce15fd1..80b1493c 100644 --- a/test/compress/issue-782.js +++ b/test/compress/issue-782.js @@ -5,19 +5,19 @@ remove_redundant_sequence_items: { (0, 1, _decorators.logThis)(); } expect: { - (0, logThis)(); + logThis(); (0, _decorators.logThis)(); } } -dont_remove_lexical_binding_sequence: { +dont_remove_this_binding_sequence: { options = { side_effects: true }; input: { (0, logThis)(); (0, _decorators.logThis)(); } expect: { - (0, logThis)(); + logThis(); (0, _decorators.logThis)(); } } diff --git a/test/compress/issue-973.js b/test/compress/issue-973.js new file mode 100644 index 00000000..41fb0e25 --- /dev/null +++ b/test/compress/issue-973.js @@ -0,0 +1,52 @@ +this_binding_conditionals: { + options = { + conditionals: true, + evaluate : true + }; + input: { + (1 && a)(); + (0 || a)(); + (0 || 1 && a)(); + (1 ? a : 0)(); + + (1 && a.b)(); + (0 || a.b)(); + (0 || 1 && a.b)(); + (1 ? a.b : 0)(); + + (1 && a[b])(); + (0 || a[b])(); + (0 || 1 && a[b])(); + (1 ? a[b] : 0)(); + } + expect: { + a(); + a(); + a(); + a(); + + (0, a.b)(); + (0, a.b)(); + (0, a.b)(); + (0, a.b)(); + + (0, a[b])(); + (0, a[b])(); + (0, a[b])(); + (0, a[b])(); + } +} + +this_binding_collapse_vars: { + options = { + collapse_vars: true, + }; + input: { + var c = a; c(); + var d = a.b; d(); + } + expect: { + a(); + (0, a.b)(); + } +} \ No newline at end of file -- 2.34.1