[Pkg-javascript-commits] [uglifyjs] 214/228: fix `delete` corner cases (#1799)

Jonas Smedegaard dr at jones.dk
Sat Apr 15 14:25:31 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository uglifyjs.

commit cf72fe552f5a51ccfe40c32e0fb86d549e0ca848
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Sat Apr 8 14:25:28 2017 +0800

    fix `delete` corner cases (#1799)
    
    - assignment
    - boolean
    - conditional
    - sequence
---
 lib/compress.js               |  62 +++++++++++-------
 test/compress/conditionals.js |  53 ++++++++++++++++
 test/compress/drop-unused.js  |  55 ++++++++++++++++
 test/compress/evaluate.js     |  79 ++++++++++++++++++++++-
 test/compress/sequences.js    | 144 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 369 insertions(+), 24 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index 03b1fef..de0ff38 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -481,15 +481,15 @@ merge(Compressor.prototype, {
     // 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) {
-            if (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name === "eval") {
-                return make_node(AST_Seq, orig, {
-                    car: make_node(AST_Number, orig, {
-                        value: 0
-                    }),
-                    cdr: val
-                });
-            }
+        if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
+            || parent instanceof AST_Call && parent.expression === orig
+                && (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
+            return make_node(AST_Seq, orig, {
+                car: make_node(AST_Number, orig, {
+                    value: 0
+                }),
+                cdr: val
+            });
         }
         return val;
     }
@@ -3103,11 +3103,27 @@ merge(Compressor.prototype, {
     });
 
     OPT(AST_UnaryPrefix, function(self, compressor){
+        var e = self.expression;
+        if (self.operator == "delete"
+            && !(e instanceof AST_SymbolRef
+                || e instanceof AST_PropAccess
+                || e instanceof AST_NaN
+                || e instanceof AST_Infinity
+                || e instanceof AST_Undefined)) {
+            if (e instanceof AST_Seq) {
+                e = e.to_array();
+                e.push(make_node(AST_True, self));
+                return AST_Seq.from_array(e).optimize(compressor);
+            }
+            return make_node(AST_Seq, self, {
+                car: e,
+                cdr: make_node(AST_True, self)
+            }).optimize(compressor);
+        }
         var seq = self.lift_sequences(compressor);
         if (seq !== self) {
             return seq;
         }
-        var e = self.expression;
         if (compressor.option("side_effects") && self.operator == "void") {
             e = e.drop_side_effect_free(compressor);
             if (e) {
@@ -3606,6 +3622,14 @@ merge(Compressor.prototype, {
         return self;
     });
 
+    function in_delete(parent) {
+        return parent instanceof AST_UnaryPrefix && parent.operator == "delete";
+    }
+
+    function is_atomic(parent, self) {
+        return parent.expression instanceof AST_SymbolRef || parent.expression.TYPE === self.TYPE;
+    }
+
     OPT(AST_Undefined, function(self, compressor){
         if (compressor.option("unsafe")) {
             var undef = find_variable(compressor, "undefined");
@@ -3620,10 +3644,7 @@ merge(Compressor.prototype, {
             }
         }
         var parent = compressor.parent();
-        if (parent instanceof AST_UnaryPrefix
-            && parent.operator == "delete"
-            && (parent.expression instanceof AST_SymbolRef
-                || parent.expression.TYPE === self.TYPE)) return self;
+        if (in_delete(parent) && is_atomic(parent, self)) return self;
         return make_node(AST_UnaryPrefix, self, {
             operator: "void",
             expression: make_node(AST_Number, self, {
@@ -3634,12 +3655,10 @@ merge(Compressor.prototype, {
 
     OPT(AST_Infinity, function(self, compressor){
         var parent = compressor.parent();
-        if (parent instanceof AST_UnaryPrefix
-            && parent.operator == "delete"
-            && (parent.expression instanceof AST_SymbolRef
-                || parent.expression.TYPE === self.TYPE))
-            return self;
+        var del = in_delete(parent);
+        if (del && is_atomic(parent, self)) return self;
         if (compressor.option("keep_infinity")
+            && !(del && !is_atomic(parent, self))
             && !find_variable(compressor, "Infinity"))
             return self;
         return make_node(AST_Binary, self, {
@@ -3655,10 +3674,7 @@ merge(Compressor.prototype, {
 
     OPT(AST_NaN, function(self, compressor){
         var parent = compressor.parent();
-        if (parent instanceof AST_UnaryPrefix
-                && parent.operator == "delete"
-                && !(parent.expression instanceof AST_SymbolRef
-                    || parent.expression.TYPE === self.TYPE)
+        if (in_delete(parent) && !is_atomic(parent, self)
             || find_variable(compressor, "NaN")) {
             return make_node(AST_Binary, self, {
                 operator: "/",
diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js
index e7ea2bb..200b487 100644
--- a/test/compress/conditionals.js
+++ b/test/compress/conditionals.js
@@ -962,3 +962,56 @@ condition_symbol_matches_consequent: {
     }
     expect_stdout: "3 7 true 4"
 }
+
+delete_conditional_1: {
+    options = {
+        booleans: true,
+        conditionals: true,
+        evaluate: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (1 ? undefined : x));
+        console.log(delete (1 ? void 0 : x));
+        console.log(delete (1 ? Infinity : x));
+        console.log(delete (1 ? 1 / 0 : x));
+        console.log(delete (1 ? NaN : x));
+        console.log(delete (1 ? 0 / 0 : x));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((1 / 0, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((NaN, !0));
+    }
+    expect_stdout: true
+}
+
+delete_conditional_2: {
+    options = {
+        booleans: true,
+        conditionals: true,
+        evaluate: true,
+        keep_infinity: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (0 ? x : undefined));
+        console.log(delete (0 ? x : void 0));
+        console.log(delete (0 ? x : Infinity));
+        console.log(delete (0 ? x : 1 / 0));
+        console.log(delete (0 ? x : NaN));
+        console.log(delete (0 ? x : 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((Infinity, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((NaN, !0));
+    }
+    expect_stdout: true
+}
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index 28118fc..99d9cac 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -974,3 +974,58 @@ issue_1715_4: {
     }
     expect_stdout: "1"
 }
+
+delete_assign_1: {
+    options = {
+        booleans: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        console.log(delete (a = undefined));
+        console.log(delete (a = void 0));
+        console.log(delete (a = Infinity));
+        console.log(delete (a = 1 / 0));
+        console.log(delete (a = NaN));
+        console.log(delete (a = 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((1 / 0, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_assign_2: {
+    options = {
+        booleans: true,
+        keep_infinity: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        console.log(delete (a = undefined));
+        console.log(delete (a = void 0));
+        console.log(delete (a = Infinity));
+        console.log(delete (a = 1 / 0));
+        console.log(delete (a = NaN));
+        console.log(delete (a = 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((Infinity, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js
index e660071..3c16e20 100644
--- a/test/compress/evaluate.js
+++ b/test/compress/evaluate.js
@@ -858,8 +858,9 @@ issue_1760_2: {
     expect_stdout: "Infinity"
 }
 
-delete_expr: {
+delete_expr_1: {
     options = {
+        booleans: true,
         evaluate: true,
     }
     input: {
@@ -872,11 +873,87 @@ delete_expr: {
     }
     expect: {
         console.log(delete undefined);
+        console.log((void 0, !0));
+        console.log(delete Infinity);
+        console.log((1 / 0, !0));
+        console.log(delete NaN);
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_expr_2: {
+    options = {
+        booleans: true,
+        evaluate: true,
+        keep_infinity: true,
+    }
+    input: {
+        console.log(delete undefined);
         console.log(delete void 0);
         console.log(delete Infinity);
         console.log(delete (1 / 0));
         console.log(delete NaN);
         console.log(delete (0 / 0));
     }
+    expect: {
+        console.log(delete undefined);
+        console.log((void 0, !0));
+        console.log(delete Infinity);
+        console.log((1 / 0, !0));
+        console.log(delete NaN);
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_binary_1: {
+    options = {
+        booleans: true,
+        evaluate: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (true && undefined));
+        console.log(delete (true && void 0));
+        console.log(delete (true && Infinity));
+        console.log(delete (true && (1 / 0)));
+        console.log(delete (true && NaN));
+        console.log(delete (true && (0 / 0)));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((1 / 0, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((NaN, !0));
+    }
+    expect_stdout: true
+}
+
+delete_binary_2: {
+    options = {
+        booleans: true,
+        evaluate: true,
+        keep_infinity: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (false || undefined));
+        console.log(delete (false || void 0));
+        console.log(delete (false || Infinity));
+        console.log(delete (false || (1 / 0)));
+        console.log(delete (false || NaN));
+        console.log(delete (false || (0 / 0)));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((Infinity, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((NaN, !0));
+    }
     expect_stdout: true
 }
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index b3c5463..699341c 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -466,3 +466,147 @@ issue_1758: {
     }
     expect_stdout: "undefined"
 }
+
+delete_seq_1: {
+    options = {
+        booleans: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (1, undefined));
+        console.log(delete (1, void 0));
+        console.log(delete (1, Infinity));
+        console.log(delete (1, 1 / 0));
+        console.log(delete (1, NaN));
+        console.log(delete (1, 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((1 / 0, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_seq_2: {
+    options = {
+        booleans: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (1, 2, undefined));
+        console.log(delete (1, 2, void 0));
+        console.log(delete (1, 2, Infinity));
+        console.log(delete (1, 2, 1 / 0));
+        console.log(delete (1, 2, NaN));
+        console.log(delete (1, 2, 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((1 / 0, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_seq_3: {
+    options = {
+        booleans: true,
+        keep_infinity: true,
+        side_effects: true,
+    }
+    input: {
+        console.log(delete (1, 2, undefined));
+        console.log(delete (1, 2, void 0));
+        console.log(delete (1, 2, Infinity));
+        console.log(delete (1, 2, 1 / 0));
+        console.log(delete (1, 2, NaN));
+        console.log(delete (1, 2, 0 / 0));
+    }
+    expect: {
+        console.log((void 0, !0));
+        console.log((void 0, !0));
+        console.log((Infinity, !0));
+        console.log((1 / 0, !0));
+        console.log((NaN, !0));
+        console.log((0 / 0, !0));
+    }
+    expect_stdout: true
+}
+
+delete_seq_4: {
+    options = {
+        booleans: true,
+        sequences: true,
+        side_effects: true,
+    }
+    input: {
+        function f() {}
+        console.log(delete (f(), undefined));
+        console.log(delete (f(), void 0));
+        console.log(delete (f(), Infinity));
+        console.log(delete (f(), 1 / 0));
+        console.log(delete (f(), NaN));
+        console.log(delete (f(), 0 / 0));
+    }
+    expect: {
+        function f() {}
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0));
+    }
+    expect_stdout: true
+}
+
+delete_seq_5: {
+    options = {
+        booleans: true,
+        keep_infinity: true,
+        sequences: true,
+        side_effects: true,
+    }
+    input: {
+        function f() {}
+        console.log(delete (f(), undefined));
+        console.log(delete (f(), void 0));
+        console.log(delete (f(), Infinity));
+        console.log(delete (f(), 1 / 0));
+        console.log(delete (f(), NaN));
+        console.log(delete (f(), 0 / 0));
+    }
+    expect: {
+        function f() {}
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0)),
+        console.log((f(), !0));
+    }
+    expect_stdout: true
+}
+
+delete_seq_6: {
+    options = {
+        booleans: true,
+        side_effects: true,
+    }
+    input: {
+        var a;
+        console.log(delete (1, a));
+    }
+    expect: {
+        var a;
+        console.log((a, !0));
+    }
+    expect_stdout: true
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list