[Pkg-javascript-commits] [uglifyjs] 113/491: introduce `unsafe_Func` (#2033)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:27 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 e9645e017f297e06506cc139922ff012fb763139
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Wed May 31 03:38:00 2017 +0800

    introduce `unsafe_Func` (#2033)
    
    Separate flag for #203 functionality.
---
 README.md                  |   2 +
 bin/uglifyjs               |   2 +-
 lib/compress.js            | 115 +++++++++++++++++++++++----------------------
 test/compress/functions.js |  22 +++++++++
 4 files changed, 83 insertions(+), 58 deletions(-)

diff --git a/README.md b/README.md
index d7e65b2..d9a0162 100644
--- a/README.md
+++ b/README.md
@@ -572,6 +572,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
   comparison are switching. Compression only works if both `comparisons` and
   `unsafe_comps` are both set to true.
 
+- `unsafe_Func` (default: false) -- compress and mangle `Function(args, code)`.
+
 - `unsafe_math` (default: false) -- optimize numerical expressions like
   `2 * x * 3` into `6 * x`, which may give imprecise floating point results.
 
diff --git a/bin/uglifyjs b/bin/uglifyjs
index ef2020c..f2aeb08 100755
--- a/bin/uglifyjs
+++ b/bin/uglifyjs
@@ -225,7 +225,7 @@ function run() {
                 col = line.length;
             }
             if (line) {
-                var limit = 78;
+                var limit = 70;
                 if (col > limit) {
                     line = line.slice(col - limit);
                     col = limit;
diff --git a/lib/compress.js b/lib/compress.js
index 374d14d..32a4d60 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -81,6 +81,7 @@ function Compressor(options, false_by_default) {
         toplevel      : !!(options && options["top_retain"]),
         unsafe        : false,
         unsafe_comps  : false,
+        unsafe_Func   : false,
         unsafe_math   : false,
         unsafe_proto  : false,
         unsafe_regexp : false,
@@ -2973,63 +2974,6 @@ merge(Compressor.prototype, {
                         operator: "!"
                     }).optimize(compressor);
                     break;
-                  case "Function":
-                    // new Function() => function(){}
-                    if (self.args.length == 0) return make_node(AST_Function, self, {
-                        argnames: [],
-                        body: []
-                    });
-                    if (all(self.args, function(x){ return x instanceof AST_String })) {
-                        // quite a corner-case, but we can handle it:
-                        //   https://github.com/mishoo/UglifyJS2/issues/203
-                        // if the code argument is a constant, then we can minify it.
-                        try {
-                            var code = "(function(" + self.args.slice(0, -1).map(function(arg){
-                                return arg.value;
-                            }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
-                            var ast = parse(code);
-                            var mangle = { ie8: compressor.option("ie8") };
-                            ast.figure_out_scope(mangle);
-                            var comp = new Compressor(compressor.options);
-                            ast = ast.transform(comp);
-                            ast.figure_out_scope(mangle);
-                            ast.mangle_names();
-                            var fun;
-                            try {
-                                ast.walk(new TreeWalker(function(node){
-                                    if (node instanceof AST_Lambda) {
-                                        fun = node;
-                                        throw ast;
-                                    }
-                                }));
-                            } catch(ex) {
-                                if (ex !== ast) throw ex;
-                            };
-                            if (!fun) return self;
-                            var args = fun.argnames.map(function(arg, i){
-                                return make_node(AST_String, self.args[i], {
-                                    value: arg.print_to_string()
-                                });
-                            });
-                            var code = OutputStream();
-                            AST_BlockStatement.prototype._codegen.call(fun, fun, code);
-                            code = code.toString().replace(/^\{|\}$/g, "");
-                            args.push(make_node(AST_String, self.args[self.args.length - 1], {
-                                value: code
-                            }));
-                            self.args = args;
-                            return self;
-                        } catch(ex) {
-                            if (ex instanceof JS_Parse_Error) {
-                                compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
-                                compressor.warn(ex.toString());
-                            } else {
-                                console.log(ex);
-                                throw ex;
-                            }
-                        }
-                    }
-                    break;
                 }
             }
             else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
@@ -3112,6 +3056,63 @@ merge(Compressor.prototype, {
                 }
             }
         }
+        if (compressor.option("unsafe_Func")
+            && exp instanceof AST_SymbolRef
+            && exp.undeclared()
+            && exp.name == "Function") {
+            // new Function() => function(){}
+            if (self.args.length == 0) return make_node(AST_Function, self, {
+                argnames: [],
+                body: []
+            });
+            if (all(self.args, function(x) {
+                return x instanceof AST_String;
+            })) {
+                // quite a corner-case, but we can handle it:
+                //   https://github.com/mishoo/UglifyJS2/issues/203
+                // if the code argument is a constant, then we can minify it.
+                try {
+                    var code = "NaN(function(" + self.args.slice(0, -1).map(function(arg) {
+                        return arg.value;
+                    }).join(",") + "){" + self.args[self.args.length - 1].value + "})";
+                    var ast = parse(code);
+                    var mangle = { ie8: compressor.option("ie8") };
+                    ast.figure_out_scope(mangle);
+                    var comp = new Compressor(compressor.options);
+                    ast = ast.transform(comp);
+                    ast.figure_out_scope(mangle);
+                    ast.mangle_names();
+                    var fun;
+                    ast.walk(new TreeWalker(function(node) {
+                        if (fun) return true;
+                        if (node instanceof AST_Lambda) {
+                            fun = node;
+                            return true;
+                        }
+                    }));
+                    var args = fun.argnames.map(function(arg, i) {
+                        return make_node(AST_String, self.args[i], {
+                            value: arg.print_to_string()
+                        });
+                    });
+                    var code = OutputStream();
+                    AST_BlockStatement.prototype._codegen.call(fun, fun, code);
+                    code = code.toString().replace(/^\{|\}$/g, "");
+                    args.push(make_node(AST_String, self.args[self.args.length - 1], {
+                        value: code
+                    }));
+                    self.args = args;
+                    return self;
+                } catch (ex) {
+                    if (ex instanceof JS_Parse_Error) {
+                        compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
+                        compressor.warn(ex.toString());
+                    } else {
+                        throw ex;
+                    }
+                }
+            }
+        }
         if (exp instanceof AST_Function) {
             if (exp.body[0] instanceof AST_Return) {
                 var value = exp.body[0].value;
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 5ebd9d1..6a9f2ae 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -245,3 +245,25 @@ hoist_funs_strict: {
     ]
     node_version: ">=4"
 }
+
+issue_203: {
+    options = {
+        keep_fargs: false,
+        side_effects: true,
+        unsafe_Func: true,
+        unused: true,
+    }
+    input: {
+        var m = {};
+        var fn = Function("require", "module", "exports", "module.exports = 42;");
+        fn(null, m, m.exports);
+        console.log(m.exports);
+    }
+    expect: {
+        var m = {};
+        var fn = Function("a", "b", "b.exports=42");
+        fn(null, m, m.exports);
+        console.log(m.exports);
+    }
+    expect_stdout: "42"
+}

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