You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
Create a Test.js file
Add the following code to it: var a = true; var b = true; var bug = () => !a && !b;
Or simply () => !a && !b;
Have it minified to Test.min.js by the Bundler and Minifier (if not automatically done so based on bundleconfig.json)
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.
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).
The text was updated successfully, but these errors were encountered:
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
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 toA || 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:
Test.js
filevar a = true; var b = true; var bug = () => !a && !b;
Or simply
() => !a && !b;
Test.min.js
by the Bundler and Minifier (if not automatically done so based onbundleconfig.json
)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 tobug=!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 asa&&!b;
and!a && !b
gets compiled asa||!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 asfunction x(n,t){return!n&&!t}
Same problem when using
||
initiallyWhen 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).The text was updated successfully, but these errors were encountered: