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

Bug in compress transformation of !typeof side_effect() #1289

Closed
kzc opened this issue Sep 12, 2016 · 5 comments
Closed

Bug in compress transformation of !typeof side_effect() #1289

kzc opened this issue Sep 12, 2016 · 5 comments

Comments

@kzc
Copy link
Contributor

kzc commented Sep 12, 2016

Incorrect optimizations:

$ echo '!typeof console.log(1);' | uglifyjs -c
WARN: Boolean expression always true [-:1,1]
WARN: Dropping side-effect-free statement [-:1,0]
$ echo 'var a = !typeof console.log(1);' | uglifyjs -c
WARN: Boolean expression always true [-:1,9]
var a=!1;
@kzc
Copy link
Contributor Author

kzc commented Sep 12, 2016

Likely fix:

--- a/lib/compress.js
+++ b/lib/compress.js
@@ -2310,10 +2310,12 @@ merge(Compressor.prototype, {
                 }
                 break;
               case "typeof":
-                // typeof always returns a non-empty string, thus it's
-                // always true in booleans
-                compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
-                return make_node(AST_True, self);
+                if (!self.expression.has_side_effects(compressor)) {
+                    // typeof always returns a non-empty string, thus it's
+                    // always true in booleans
+                    compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
+                    return make_node(AST_True, self);
+                }
             }
             if (e instanceof AST_Binary && self.operator == "!") {
                 self = best_of(self, e.negate(compressor));

After patch applied:

$ echo '!typeof console.log(1);' | bin/uglifyjs -c
!typeof console.log(1);
$ echo 'var a = !typeof console.log(1);' | bin/uglifyjs -c
var a=!typeof console.log(1);

It's not optimal, but not incorrect.

@rvanvelzen
Copy link
Collaborator

Different solution:

diff --git a/lib/compress.js b/lib/compress.js
index 8a08572..11ea86d 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -2313,6 +2313,12 @@ merge(Compressor.prototype, {
                 // typeof always returns a non-empty string, thus it's
                 // always true in booleans
                 compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
+                if (self.expression.has_side_effects(compressor)) {
+                  return make_node(AST_Seq, self, {
+                      car: self.expression,
+                      cdr: make_node(AST_True, self)
+                  });
+                }
                 return make_node(AST_True, self);
             }
             if (e instanceof AST_Binary && self.operator == "!") {
$ echo '!typeof console.log(1);' | bin/uglifyjs -c
WARN: Boolean expression always true [-:1,1]
console.log(1),!1;
$ echo 'var a = !typeof console.log(1);' | bin/uglifyjs -c
WARN: Boolean expression always true [-:1,9]
var a=(console.log(1),!1);

These could probably be optimized further later, but at least the operator is dropped, which is something?

@kzc
Copy link
Contributor Author

kzc commented Sep 12, 2016

Is it worth optimizing a typeof of an expression with a side effect in a boolean context?

This is so rare in practise and is almost always incorrect code.

Look at the cost/benefit ratio versus the risk of an incorrect assumption.

@rvanvelzen
Copy link
Collaborator

Except for typos, I don't believe this case would ever appear in the wild. That having been said, I don't see any reason not to optimize this case.

@kzc
Copy link
Contributor Author

kzc commented Sep 12, 2016

@rvanvelzen I don't think it's worth the complexity for this rare case, but please feel free to fix as you see fit.

@kzc kzc changed the title Incorrect optimization of !typeof side_effect() Bug in compress transformation of !typeof side_effect() Sep 15, 2016
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

2 participants