[Pkg-javascript-commits] [uglifyjs] 199/491: improve `mangle.properties` (#2261)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:35 UTC 2018


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

js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.

commit a845897758aa2cbccf71f37643d31b08cdd22a0e
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Sat Jul 29 23:02:04 2017 +0800

    improve `mangle.properties` (#2261)
    
    - include dead code when `keep_quoted`
    - unify `keep_quoted` & `reserved`
    - make `test/run-tests.js` consistent with `minify()`
    
    fixes #2256
---
 lib/minify.js               | 13 ++++++-
 lib/propmangle.js           | 95 +++++++++++++++++----------------------------
 test/compress/issue-1321.js | 38 ++++++++++--------
 test/compress/issue-1770.js | 12 ++++--
 test/compress/issue-747.js  | 12 ++++--
 test/compress/properties.js | 88 +++++++++++++++++++++++++++--------------
 test/exports.js             |  1 +
 test/mocha/minify.js        | 11 ++++++
 test/run-tests.js           | 16 +++++---
 9 files changed, 167 insertions(+), 119 deletions(-)

diff --git a/lib/minify.js b/lib/minify.js
index b4bfe45..773e953 100644
--- a/lib/minify.js
+++ b/lib/minify.js
@@ -68,6 +68,7 @@ function minify(files, options) {
         set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
         set_shorthand("toplevel", options, [ "compress", "mangle" ]);
         set_shorthand("warnings", options, [ "compress" ]);
+        var quoted_props;
         if (options.mangle) {
             options.mangle = defaults(options.mangle, {
                 cache: options.nameCache && (options.nameCache.vars || {}),
@@ -78,11 +79,16 @@ function minify(files, options) {
                 reserved: [],
                 toplevel: false,
             }, true);
-            if (options.nameCache && options.mangle.properties) {
+            if (options.mangle.properties) {
                 if (typeof options.mangle.properties != "object") {
                     options.mangle.properties = {};
                 }
-                if (!("cache" in options.mangle.properties)) {
+                if (options.mangle.properties.keep_quoted) {
+                    quoted_props = options.mangle.properties.reserved;
+                    if (!Array.isArray(quoted_props)) quoted_props = [];
+                    options.mangle.properties.reserved = quoted_props;
+                }
+                if (options.nameCache && !("cache" in options.mangle.properties)) {
                     options.mangle.properties.cache = options.nameCache.props || {};
                 }
             }
@@ -125,6 +131,9 @@ function minify(files, options) {
             }
             toplevel = options.parse.toplevel;
         }
+        if (quoted_props) {
+            reserve_quoted_keys(toplevel, quoted_props);
+        }
         if (options.wrap) {
             toplevel = toplevel.wrap_commonjs(options.wrap);
         }
diff --git a/lib/propmangle.js b/lib/propmangle.js
index 4949075..36a67e8 100644
--- a/lib/propmangle.js
+++ b/lib/propmangle.js
@@ -67,6 +67,34 @@ function find_builtins(reserved) {
     }
 }
 
+function reserve_quoted_keys(ast, reserved) {
+    function add(name) {
+        push_uniq(reserved, name);
+    }
+
+    ast.walk(new TreeWalker(function(node) {
+        if (node instanceof AST_ObjectKeyVal && node.quote) {
+            add(node.key);
+        } else if (node instanceof AST_Sub) {
+            addStrings(node.property, add);
+        }
+    }));
+}
+
+function addStrings(node, add) {
+    node.walk(new TreeWalker(function(node) {
+        if (node instanceof AST_Sequence) {
+            addStrings(node.expressions[node.expressions.length - 1], add);
+        } else if (node instanceof AST_String) {
+            add(node.value);
+        } else if (node instanceof AST_Conditional) {
+            addStrings(node.consequent, add);
+            addStrings(node.alternative, add);
+        }
+        return true;
+    }));
+}
+
 function mangle_properties(ast, options) {
     options = defaults(options, {
         builtins: false,
@@ -91,7 +119,6 @@ function mangle_properties(ast, options) {
     }
 
     var regex = options.regex;
-    var keep_quoted = options.keep_quoted;
 
     // note debug is either false (disabled), or a string of the debug suffix to use (enabled).
     // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
@@ -104,12 +131,11 @@ function mangle_properties(ast, options) {
 
     var names_to_mangle = [];
     var unmangleable = [];
-    var to_keep = {};
 
     // step 1: find candidates to mangle
     ast.walk(new TreeWalker(function(node){
         if (node instanceof AST_ObjectKeyVal) {
-            add(node.key, keep_quoted && node.quote);
+            add(node.key);
         }
         else if (node instanceof AST_ObjectProperty) {
             // setter or getter, since KeyVal is handled above
@@ -119,15 +145,14 @@ function mangle_properties(ast, options) {
             add(node.property);
         }
         else if (node instanceof AST_Sub) {
-            addStrings(node.property, keep_quoted);
+            addStrings(node.property, add);
         }
     }));
 
     // step 2: transform the tree, renaming properties
     return ast.transform(new TreeTransformer(function(node){
         if (node instanceof AST_ObjectKeyVal) {
-            if (!(keep_quoted && node.quote))
-                node.key = mangle(node.key);
+            node.key = mangle(node.key);
         }
         else if (node instanceof AST_ObjectProperty) {
             // setter or getter
@@ -136,22 +161,9 @@ function mangle_properties(ast, options) {
         else if (node instanceof AST_Dot) {
             node.property = mangle(node.property);
         }
-        else if (node instanceof AST_Sub) {
-            if (!keep_quoted)
-                node.property = mangleStrings(node.property);
+        else if (!options.keep_quoted && node instanceof AST_Sub) {
+            node.property = mangleStrings(node.property);
         }
-        // else if (node instanceof AST_String) {
-        //     if (should_mangle(node.value)) {
-        //         AST_Node.warn(
-        //             "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
-        //                 file : node.start.file,
-        //                 line : node.start.line,
-        //                 col  : node.start.col,
-        //                 prop : node.value
-        //             }
-        //         );
-        //     }
-        // }
     }));
 
     // only function declarations after this line
@@ -167,19 +179,13 @@ function mangle_properties(ast, options) {
     }
 
     function should_mangle(name) {
-        if (keep_quoted && name in to_keep) return false;
         if (regex && !regex.test(name)) return false;
         if (reserved.indexOf(name) >= 0) return false;
         return cache.props.has(name)
             || names_to_mangle.indexOf(name) >= 0;
     }
 
-    function add(name, keep) {
-        if (keep) {
-            to_keep[name] = true;
-            return;
-        }
-
+    function add(name) {
         if (can_mangle(name))
             push_uniq(names_to_mangle, name);
 
@@ -199,19 +205,16 @@ function mangle_properties(ast, options) {
                 // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
                 var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
 
-                if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
+                if (can_mangle(debug_mangled)) {
                     mangled = debug_mangled;
                 }
             }
 
             // either debug mode is off, or it is on and we could not use the mangled name
             if (!mangled) {
-                // Note: `can_mangle()` does not check if the name collides with the `to_keep` set
-                // (filled with quoted properties when `keep_quoted` is set). Make sure we add this
-                // check so we don't collide with a quoted name.
                 do {
                     mangled = base54(++cache.cname);
-                } while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
+                } while (!can_mangle(mangled));
             }
 
             cache.props.set(name, mangled);
@@ -219,32 +222,6 @@ function mangle_properties(ast, options) {
         return mangled;
     }
 
-    function addStrings(node, keep) {
-        var out = {};
-        try {
-            (function walk(node){
-                node.walk(new TreeWalker(function(node){
-                    if (node instanceof AST_Sequence) {
-                        walk(node.expressions[node.expressions.length - 1]);
-                        return true;
-                    }
-                    if (node instanceof AST_String) {
-                        add(node.value, keep);
-                        return true;
-                    }
-                    if (node instanceof AST_Conditional) {
-                        walk(node.consequent);
-                        walk(node.alternative);
-                        return true;
-                    }
-                    throw out;
-                }));
-            })(node);
-        } catch(ex) {
-            if (ex !== out) throw ex;
-        }
-    }
-
     function mangleStrings(node) {
         return node.transform(new TreeTransformer(function(node){
             if (node instanceof AST_Sequence) {
diff --git a/test/compress/issue-1321.js b/test/compress/issue-1321.js
index 6b92291..e55696d 100644
--- a/test/compress/issue-1321.js
+++ b/test/compress/issue-1321.js
@@ -1,6 +1,8 @@
 issue_1321_no_debug: {
-    mangle_props = {
-        keep_quoted: true
+    mangle = {
+        properties: {
+            keep_quoted: true,
+        },
     }
     input: {
         var x = {};
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
     }
     expect: {
         var x = {};
-        x.o = 1;
-        x["a"] = 2 * x.o;
-        console.log(x.o, x["a"]);
+        x.x = 1;
+        x["a"] = 2 * x.x;
+        console.log(x.x, x["a"]);
     }
     expect_stdout: true
 }
 
 issue_1321_debug: {
-    mangle_props = {
-        keep_quoted: true,
-        debug: ""
+    mangle = {
+        properties: {
+            debug: "",
+            keep_quoted: true,
+        },
     }
     input: {
         var x = {};
@@ -30,16 +34,18 @@ issue_1321_debug: {
     }
     expect: {
         var x = {};
-        x.o = 1;
-        x["_$foo$_"] = 2 * x.o;
-        console.log(x.o, x["_$foo$_"]);
+        x.x = 1;
+        x["_$foo$_"] = 2 * x.x;
+        console.log(x.x, x["_$foo$_"]);
     }
     expect_stdout: true
 }
 
 issue_1321_with_quoted: {
-    mangle_props = {
-        keep_quoted: false
+    mangle = {
+        properties: {
+            keep_quoted: false,
+        },
     }
     input: {
         var x = {};
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
     }
     expect: {
         var x = {};
-        x.o = 1;
-        x["x"] = 2 * x.o;
-        console.log(x.o, x["x"]);
+        x.x = 1;
+        x["o"] = 2 * x.x;
+        console.log(x.x, x["o"]);
     }
     expect_stdout: true
 }
diff --git a/test/compress/issue-1770.js b/test/compress/issue-1770.js
index f296a40..f63f845 100644
--- a/test/compress/issue-1770.js
+++ b/test/compress/issue-1770.js
@@ -1,5 +1,7 @@
 mangle_props: {
-    mangle_props = {}
+    mangle = {
+        properties: true,
+    }
     input: {
         var obj = {
             undefined: 1,
@@ -54,10 +56,12 @@ mangle_props: {
 }
 
 numeric_literal: {
+    mangle = {
+        properties: true,
+    }
     beautify = {
         beautify: true,
     }
-    mangle_props = {}
     input: {
         var obj = {
             0: 0,
@@ -105,7 +109,9 @@ numeric_literal: {
 }
 
 identifier: {
-    mangle_props = {}
+    mangle = {
+        properties: true,
+    }
     input: {
         var obj = {
             abstract: 1,
diff --git a/test/compress/issue-747.js b/test/compress/issue-747.js
index 1f7079c..e074305 100644
--- a/test/compress/issue-747.js
+++ b/test/compress/issue-747.js
@@ -1,6 +1,8 @@
 dont_reuse_prop: {
-    mangle_props = {
-        regex: /asd/
+    mangle = {
+        properties: {
+            regex: /asd/,
+        },
     }
     input: {
         "aaaaaaaaaabbbbb";
@@ -20,8 +22,10 @@ dont_reuse_prop: {
 }
 
 unmangleable_props_should_always_be_reserved: {
-    mangle_props = {
-        regex: /asd/
+    mangle = {
+        properties: {
+            regex: /asd/,
+        },
     }
     input: {
         "aaaaaaaaaabbbbb";
diff --git a/test/compress/properties.js b/test/compress/properties.js
index dda2e74..c2c43f6 100644
--- a/test/compress/properties.js
+++ b/test/compress/properties.js
@@ -128,9 +128,11 @@ evaluate_string_length: {
 }
 
 mangle_properties: {
-    mangle_props = {
-        keep_quoted: false
-    };
+    mangle = {
+        properties: {
+            keep_quoted: false,
+        },
+    }
     input: {
         a["foo"] = "bar";
         a.color = "red";
@@ -139,11 +141,11 @@ mangle_properties: {
         a['run']({color: "blue", foo: "baz"});
     }
     expect: {
-        a["o"] = "bar";
-        a.a = "red";
-        x = {r: 10};
-        a.b(x.r, a.o);
-        a['b']({a: "blue", o: "baz"});
+        a["a"] = "bar";
+        a.b = "red";
+        x = {o: 10};
+        a.r(x.o, a.a);
+        a['r']({b: "blue", a: "baz"});
     }
 }
 
@@ -151,8 +153,10 @@ mangle_unquoted_properties: {
     options = {
         properties: false
     }
-    mangle_props = {
-        keep_quoted: true
+    mangle = {
+        properties: {
+            keep_quoted: true,
+        },
     }
     beautify = {
         beautify: false,
@@ -181,24 +185,26 @@ mangle_unquoted_properties: {
         function f1() {
             a["foo"] = "bar";
             a.color = "red";
-            a.o = 2;
-            x = {"bar": 10, f: 7};
-            a.f = 9;
+            a.r = 2;
+            x = {"bar": 10, b: 7};
+            a.b = 9;
         }
         function f2() {
             a.foo = "bar";
             a['color'] = "red";
-            x = {bar: 10, f: 7};
-            a.f = 9;
-            a.o = 3;
+            x = {bar: 10, b: 7};
+            a.b = 9;
+            a.r = 3;
         }
     }
 }
 
 mangle_debug: {
-    mangle_props = {
-        debug: ""
-    };
+    mangle = {
+        properties: {
+            debug: "",
+        },
+    }
     input: {
         a.foo = "bar";
         x = { baz: "ban" };
@@ -210,9 +216,11 @@ mangle_debug: {
 }
 
 mangle_debug_true: {
-    mangle_props = {
-        debug: true
-    };
+    mangle = {
+        properties: {
+            debug: true,
+        },
+    }
     input: {
         a.foo = "bar";
         x = { baz: "ban" };
@@ -224,9 +232,11 @@ mangle_debug_true: {
 }
 
 mangle_debug_suffix: {
-    mangle_props = {
-        debug: "XYZ"
-    };
+    mangle = {
+        properties: {
+            debug: "XYZ",
+        },
+    }
     input: {
         a.foo = "bar";
         x = { baz: "ban" };
@@ -241,10 +251,12 @@ mangle_debug_suffix_keep_quoted: {
     options = {
         properties: false
     }
-    mangle_props = {
-        keep_quoted: true,
-        debug: "XYZ",
-        reserved: []
+    mangle = {
+        properties: {
+            debug: "XYZ",
+            keep_quoted: true,
+            reserved: [],
+        },
     }
     beautify = {
         beautify: false,
@@ -774,3 +786,21 @@ issue_2208_5: {
     }
     expect_stdout: "42"
 }
+
+issue_2256: {
+    options = {
+        side_effects: true,
+    }
+    mangle = {
+        properties: {
+            keep_quoted: true,
+        },
+    }
+    input: {
+        ({ "keep": 1 });
+        g.keep = g.change;
+    }
+    expect: {
+        g.keep = g.g;
+    }
+}
diff --git a/test/exports.js b/test/exports.js
index f50b772..997ad51 100644
--- a/test/exports.js
+++ b/test/exports.js
@@ -8,6 +8,7 @@ exports["defaults"] = defaults;
 exports["mangle_properties"] = mangle_properties;
 exports["minify"] = minify;
 exports["parse"] = parse;
+exports["reserve_quoted_keys"] = reserve_quoted_keys;
 exports["string_template"] = string_template;
 exports["tokenizer"] = tokenizer;
 exports["is_identifier"] = is_identifier;
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index 88e9c4e..fc7332f 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -124,6 +124,17 @@ describe("minify", function() {
             assert.strictEqual(result.code,
                     'a["foo"]="bar",a.a="red",x={"bar":10};');
         });
+        it("Should not mangle quoted property within dead code", function() {
+            var result = Uglify.minify('({ "keep": 1 }); g.keep = g.change;', {
+                mangle: {
+                    properties: {
+                        keep_quoted: true
+                    }
+                }
+            });
+            if (result.error) throw result.error;
+            assert.strictEqual(result.code, "g.keep=g.g;");
+        });
     });
 
     describe("inSourceMap", function() {
diff --git a/test/run-tests.js b/test/run-tests.js
index 6b8c9dd..0051c6c 100755
--- a/test/run-tests.js
+++ b/test/run-tests.js
@@ -111,18 +111,22 @@ function run_compress_tests() {
                 };
                 if (!options.warnings) options.warnings = true;
             }
+            if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {
+                var quoted_props = test.mangle.properties.reserved;
+                if (!Array.isArray(quoted_props)) quoted_props = [];
+                test.mangle.properties.reserved = quoted_props;
+                U.reserve_quoted_keys(input, quoted_props);
+            }
             var cmp = new U.Compressor(options, true);
             var output = cmp.compress(input);
             output.figure_out_scope(test.mangle);
-            if (test.mangle || test.mangle_props) {
+            if (test.mangle) {
                 U.base54.reset();
                 output.compute_char_frequency(test.mangle);
-            }
-            if (test.mangle) {
                 output.mangle_names(test.mangle);
-            }
-            if (test.mangle_props) {
-                output = U.mangle_properties(output, test.mangle_props);
+                if (test.mangle.properties) {
+                    output = U.mangle_properties(output, test.mangle.properties);
+                }
             }
             output = make_code(output, output_options);
             if (expect != output) {

-- 
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