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

Functions are sometimes put inside if blocks, breaking current Firefox, Safari & IE 10 #1052

Closed
mgol opened this issue Apr 23, 2016 · 11 comments

Comments

@mgol
Copy link
Contributor

mgol commented Apr 23, 2016

This is related to #179. Current Firefox & Safari as well as IE 10 don't accept function declarations inside and UglifyJS 2.6.2 with compress options:

{
    "hoist_funs": false,
    loops: false,
    unused: false
}

sometimes applies such a treatment.

This caused syntax errors in mentioned browsers on current jQuery master (source from commit 3befe5911a) where we enabled strict mode. More specifically, this function in the built file is transformed to be contained in a negation of this if.

mgol added a commit to jquery/jquery that referenced this issue Apr 23, 2016
This commit increases the gzipped size by 90 bytes so a better solution
is needed but, at the same time, it disables the very optimizations
that are causing strict mode violations in Firefox 45, Safari 9 & IE 10.

Refs 7608437
Refs mishoo/UglifyJS#1052
@kzc
Copy link
Contributor

kzc commented Apr 23, 2016

@mgol There are too many external links for me to understand the issue. Can you please post in this ticket (1) a complete reduced test case of the javascript input, and (2) the uglify output with a comment beside the problematic generated code.

@mgol
Copy link
Contributor Author

mgol commented Apr 23, 2016

Sorry, I should've started with a reduced test case, I just hoped someone will know what's going on.

The test case is as follows - with the source file:

"use strict";

( function() {
    if ( !window ) {
        return;
    }

    function f() {}
    function g() {}
} )();

running:

uglifyjs test-case.js -c hoist_funs=false -c loops=false -c unused=false -m -b

results in:

"use strict";

!function() {
    if (window) {
        function n() {}
        function i() {}
    }
}();

which wasn't allowed in ES5 & many browsers (including current Firefox, Safari & IE 10) throw an immediate Syntax Error when such code is encountered. The original code works fine.

Note that if you remove the second named function declaration (g) from the source, you get this:

"use strict";

!function() {
    if (window) function i() {}
}();

which is a Syntax Error even in current Chrome.

@rvanvelzen
Copy link
Collaborator

Is there a specific reason for disabling hoist_funs? At least for now, enabling it should resolve this issue.

E.g., the output with hoist_funs:

"use strict";

!function() {
    function n() {}
    function i() {}
    !window;
}();

... which is functionally the same.

@mgol
Copy link
Contributor Author

mgol commented Apr 23, 2016

If we don't disable hoist_funs, the full jQuery minified+gzipped build will get larger by 496 bytes. That's a lot from our perspective, we sometimes reject non-critical patches slightly improving some logic if it bumped the size by 100-200 bytes.

@mgol
Copy link
Contributor Author

mgol commented Apr 23, 2016

For now I resolved it by also disabling if_return but it also increases the size; not by 496 bytes but by 90 but it's still a significant amount.

@mishoo
Copy link
Owner

mishoo commented Apr 23, 2016

I agree it is a bug and it should be fixed.

@rvanvelzen
Copy link
Collaborator

I've a potential fix, PR coming up.

@mishoo
Copy link
Owner

mishoo commented Apr 23, 2016

@rvanvelzen Thanks! It looks good to me. Can't do a proper review right now though.

@mgol Can you test with the attached patch?

Any case, this issue makes me think that hoisting is actually the right thing to do—even if it increases the file size. For a library the size of jQuery, 500 more bytes shouldn't be a big deal…

@mgol
Copy link
Contributor Author

mgol commented Apr 24, 2016

I'll look into it tomorrow.

@mgol
Copy link
Contributor Author

mgol commented Apr 25, 2016

@mishoo #1053 (comment). The PR LGTM.

@mgol
Copy link
Contributor Author

mgol commented Apr 25, 2016

Any case, this issue makes me think that hoisting is actually the right thing to do—even if it increases the file size. For a library the size of jQuery, 500 more bytes shouldn't be a big deal…

Full jQuery is currently around 30 KB minified+gzipped. 500 bytes might seem like not a lot but if we didn't care about such changes, landing a couple of them could easily bump the size to 33 KB or more. For a library loaded by half of the internet, that's actually making a big difference.

mgol added a commit to jquery/jquery that referenced this issue Jun 8, 2016
A bug in UglifyJS was causing function declarations to sometimes be put
in blocks which wasn't well specified in ES5 so it may break some browsers.
This bump will prevent the issue from occurring in any potential future
releae in this line.

Refs #3153
Refs mishoo/UglifyJS#1052
mgol added a commit to jquery/jquery that referenced this issue Jun 8, 2016
A bug in UglifyJS was causing function declarations to sometimes be put
in blocks which wasn't well specified in ES5 so it may break some browsers.
This bump will prevent the issue from occurring in any potential future
releae in this line.

(cherry-picked from b14ce54)

Refs #3153
Refs mishoo/UglifyJS#1052
alexlamsl added a commit to alexlamsl/UglifyJS that referenced this issue May 26, 2017
Previous fiix for mishoo#1052 perturbs declaration order of functions which leads to incorrect behaviour under "use strict".
alexlamsl added a commit that referenced this issue May 27, 2017
Previous fiix for #1052 perturbs declaration order of functions which leads to incorrect behaviour under "use strict".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants