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

Boolean Logic using arrow function with && gets minified to || with some logic inversed. #599

Open
pitus opened this issue Jul 5, 2023 · 0 comments
Labels

Comments

@pitus
Copy link

pitus commented Jul 5, 2023

Describe the bug
I have some code that's calculating a boolean expression based on multiple negated tests that are && together.
Once minified, the logic is converted to || while negation is removed from all but the last boolean component. If it was optimized using De Morgan's law then it's missing an extra ! in front that should negate the entire expression but it also shouldn't leave the ! in front of the last element ...
Instead of converting !A && !B && !C to !(A || B || C) it converts it to A || B || !C which is a serious problem as I may have many instances of similar logic in my code and I can no longer trust that the minifier didn't mess up any of it.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Test.js file
  2. Add the following code to it:
    var a = true; var b = true; var bug = () => !a && !b;
    Or simply () => !a && !b;
  3. Have it minified to Test.min.js by the Bundler and Minifier (if not automatically done so based on bundleconfig.json)
  4. Review the Text.min.js file, it now contains an invalid code (messed up boolean logic)
    var a=!0,b=!0,bug=()=>a||!b;
    Or simply ()=>a||!b;

Expected behavior
The content of Test.min.js should have an extra !(_expression_) added and no ! on the last element:
var a=!0,b=!0,bug=()=>!(a||b);
Or it should have left it unchanged as:
var a=!0,b=!0,bug=()=>!a&&!b;

Observation
This seems to only happen when there's an arrow function involved in the logic.
So var bug = !a && !b; compiles correctly to bug=!a&&!b;
Also, it only happens when all but the last element are negated using ! - the last one doesn't have to be negated, it'll simply be copied as is, but if any of the expressions prior to it are not negated, the whole thing is compiled correctly.
Interesting test: () => !!!a || !b; gets compiled as ()=>!!a&&!b; so it simply removes one of the ! in all but last element.
Another simple example that fails: !a || !b; gets compiled as a&&!b; and !a && !b gets compiled as a||!b so it's not just with arrow functions after all - but it works correctly when it's an expression returned from a regular function or class method:
function x( a, b ) { return !a && !b; } gets compiled correctly as function x(n,t){return!n&&!t}

Same problem when using || initially
When the original expression is () => !a || !b;
It gets compiled to ()=>a&&!b;
So the Minifier seems to have an issue with boolean expression elements that are negated within an arrow function.

Additional context
() => !a && b; gets compiled to ()=>a||b;

Work-around
I had to convert my expression using De Morgan's law manually so that it doesn't attempt to do this on its own. So if I enter in my original source the following:
var a = true; var b = true; var bug = () => !(a || b);
It gets properly minimized as:
var a=!0,b=!0,bug=()=>!(a||b);

Note that if there are more than 2 elements, only the last one has the ! in front of it.
I've also seen it compile with no ! left at the last element, but I can't reproduce that anymore (don't remember the exact code).

@pitus pitus added the bug label Jul 5, 2023
@pitus pitus changed the title Boolean Logic minified with reversed result Boolean Logic using arrow function with && gets minified to || with some logic inversed. Jul 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant