Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline single-use functions that are not constant expressions #2428

Closed
kzc opened this issue Nov 4, 2017 · 4 comments · Fixed by #2434
Closed

inline single-use functions that are not constant expressions #2428

kzc opened this issue Nov 4, 2017 · 4 comments · Fixed by #2434

Comments

@kzc
Copy link
Contributor

kzc commented Nov 4, 2017

Bug report or feature request?

feature request

ES5 or ES6+ input?

either

Uglify version (uglifyjs -V)

3.1.6

JavaScript input

From #2427 (comment):

It'd nice to be able to inline functions that are not constant expressions, such as:

!function(){
    function bar(k) {
        console.log(k);
    }
    function foo(x) {
        return bar(x);
    }
    function baz(a) {
        foo(a);
    }
    baz(Math.random());
    baz(Math.random());
}();

which should result in:

function baz(a) {
    console.log(a);
}
baz(Math.random());
baz(Math.random());
@kzc
Copy link
Contributor Author

kzc commented Nov 4, 2017

Another test case:

!function(){
    function bar(o) {
        return {
            a: o.x,
            b: o.y
        };
    }
    function foo(obj) {
        console.log(bar(obj));
    }
    foo({x: 1});
    foo({y: 2});
}();

Should produce:

    function foo(obj) {
        console.log({
            a: obj.x,
            b: obj.y
        });
    }
    foo({x: 1});
    foo({y: 2});

@alexlamsl
Copy link
Collaborator

--- a/lib/compress.js
+++ b/lib/compress.js
@@ -150,7 +150,9 @@ merge(Compressor.prototype, {
         }
         var passes = +this.options.passes || 1;
         var last_count = 1 / 0;
+        var mangle = { ie8: this.option("ie8") };
         for (var pass = 0; pass < passes; pass++) {
+            node.figure_out_scope(mangle);
             if (pass > 0 || this.option("reduce_vars"))
                 node.reset_opt_flags(this);
             node = node.transform(this);
diff --git a/lib/minify.js b/lib/minify.js
index 773e953..f9d726b 100644
--- a/lib/minify.js
+++ b/lib/minify.js
@@ -137,11 +137,9 @@ function minify(files, options) {
         if (options.wrap) {
             toplevel = toplevel.wrap_commonjs(options.wrap);
         }
-        if (timings) timings.scope1 = Date.now();
-        if (options.compress) toplevel.figure_out_scope(options.mangle);
         if (timings) timings.compress = Date.now();
         if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
-        if (timings) timings.scope2 = Date.now();
+        if (timings) timings.scope = Date.now();
         if (options.mangle) toplevel.figure_out_scope(options.mangle);
         if (timings) timings.mangle = Date.now();
         if (options.mangle) {
@@ -199,9 +197,9 @@ function minify(files, options) {
         if (timings) {
             timings.end = Date.now();
             result.timings = {
-                parse: 1e-3 * (timings.scope1 - timings.parse),
-                scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2),
-                compress: 1e-3 * (timings.scope2 - timings.compress),
+                parse: 1e-3 * (timings.compress - timings.parse),
+                compress: 1e-3 * (timings.scope - timings.compress),
+                scope: 1e-3 * (timings.mangle - timings.scope),
                 mangle: 1e-3 * (timings.properties - timings.mangle),
                 properties: 1e-3 * (timings.output - timings.properties),
                 output: 1e-3 * (timings.end - timings.output),

gives:

$ uglifyjs 2428.js -b bracketize -c keep_fargs=0,unsafe,passes=2
!function() {
    function baz(a) {
        console.log(a);
    }
    baz(Math.random()), baz(Math.random());
}();

@alexlamsl
Copy link
Collaborator

With current master and a variation of #2428 (comment):

!function(){
    function bar(o) {
        return {
            a: o.x,
            b: o.y
        };
    }
    function foo(obj) {
        console.log(bar(obj));
    }
    foo({x: 1, y: 2});
}();

it does give the minimal result:

$ uglifyjs test.js -b bracketize -c unsafe,passes=3
console.log({
    a: 1,
    b: 2
});

@kzc
Copy link
Contributor Author

kzc commented Nov 5, 2017

@alexlamsl I didn't understand your patch at first since it was altering time stat reporting - until I saw figure_out_scope() was called for each pass.

Clever!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants