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
Inconsistent evaluation of strings in no-constant-condition #11181
Inconsistent evaluation of strings in no-constant-condition #11181
Comments
Thanks for the report. When I try this locally by enabling |
Hi @nzakas, thanks for getting back to me. To clarify, the rule is definitely enabled but is not triggered by the first example: However it is triggered for the following examples: Hope that helps 😄 |
Thanks for clarifying. This does look like a bug. If you'd like to take a look, I'm guessing the issue is somewhere in here: |
Cool ok, I’ll give it a go at some point over the Christmas break!
… On 19 Dec 2018, at 3:27 pm, Nicholas C. Zakas ***@***.***> wrote:
Thanks for clarifying. This does look like a bug.
If you'd like to take a look, I'm guessing the issue is somewhere in here:
https://github.com/eslint/eslint/blob/master/lib/rules/no-constant-condition.js#L106
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
--
*This e-mail is confidential, please read our related legal terms
<https://thanksbox.co/legal/email/>.*
|
Hey, so I've had a look at this but thought I'd like to sense check some stuff before doing any more. My first step was to add some examples of invalid code to the tests: { code: "if(abc==='str' || 'str'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if('str' || abc==='str'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
{ code: "if(a || 'str' || abc==='str'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] } This was then causing the tests to fail (as expected) so I started having a look at the rule. The following line (https://github.com/eslint/eslint/blob/master/lib/rules/no-constant-condition.js#L112): return (isLeftConstant && isRightConstant) || isLeftShortCircuit || isRightShortCircuit; ...doesn't look correct to me. If I've understood the rule correctly, then any constant in a conditional should be marked as an error, so I updated it to this: return isLeftConstant || isRightConstant || isLeftShortCircuit || isRightShortCircuit; This causes my newly added tests to pass, but also causes some existing tests to fail. However I'm not entirely sure these tests are correct. The following are all marked as valid examples, yet all of them contain a constant: "if (void a || a);",
"if (a || void a);",
"if(false || abc==='str'){}",
"if(true && abc==='str'){}",
"if(typeof 'str' && abc==='str'){}",
"if(abc==='str' || false || def ==='str'){}",
"if(true && abc==='str' || def ==='str'){}",
"if(true && typeof abc==='string'){}",
"if(a === 'str' && typeof b){}" If you agree these tests are incorrect I'll be happy to change them to be incorrect examples and raise a PR. If not, then some clarification around the intention of this rule would be useful. Thanks! |
Hi @MerlinBB, thank you for sharing your detailed research! I don't think the intent of the rule is to look for any constants in the condition. Rather, the goal should be to see if the condition (as a whole) will always result in the same value. Let's take this example: In this case, It seems more likely to be that we need to look at the logic that flags a single given expression as constant and ensure string literals are detected as constants. At this point, based on what you've shown so far, I don't think there's anything wrong with the line that checks the logical expression (and/or) in terms of whether both terms are constant or there's a constant short circuit. Hope this helps! Let me know if I can clarify anything. |
That's correct. The intent of the rule is to determine if the condition can
ever change based on the inputs. In the case of logical OR, something that
always evaluated to false on the left means that the right will always be
used.
…On Wed, Dec 26, 2018 at 4:58 PM Kevin Partington ***@***.***> wrote:
Hi @MerlinBB <https://github.com/MerlinBB>, thank you for sharing your
detailed research!
I don't think the intent of the rule is to look for any constants in the
condition. Rather, the goal should be to see if the condition will always
result in the same value.
Let's take this example: if (void a || a);
In this case, void a is a constant in that it will always return
undefined. As you probably know, undefined is falsy. In the case of an
*or* conditional, that means we have to look at the right side. The right
side here is a variable reference, so it's not constant and the rule
shouldn't report. However, I would expect if (void a && a); to be
invalid, since the undefined value will short-circuit in that case.
It seems more likely to be that we need to look at the logic that flags a
single given expression as constant and ensure string literals are detected
as constants. At this point, based on what you've shown so far, I don't
think there's anything wrong with the line that checks the logical
expression (and/or) in terms of whether both terms are constant or there's
a constant short circuit.
Hope this helps! Let me know if I can clarify anything.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#11181 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AACWksWybd3xBKXVazEzwNYcuKIG7Ab6ks5u9BtDgaJpZM4ZLqe2>
.
--
______________________________
Nicholas C. Zakas
@SlickNet
Author, Principles of Object-Oriented JavaScript <http://amzn.to/29Pmfrm>
Author, Understanding ECMAScript 6 <http://amzn.to/29K1mIy>
|
Hey guys, thanks for the update...
Yep this makes sense, I think in this case we also need to know if right side is truthy too. The following seems to do the job, does this look right to you? return (isLeftConstant && isRightConstant) ||
(node.operator === "||" && isRightConstant && node.right.value) ||
isLeftShortCircuit ||
isRightShortCircuit; |
That seems correct to me. I would say that we probably need a comment there to indicate that |
Awesome! Ok I'll add that and raise a PR. |
Tell us about your environment
What parser are you using?
babel-eslint
Please show your full configuration:
Configuration
What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.
What did you expect to happen?
An error should be thrown as a string will always evaluate to true. This would be consistent with the following examples where errors are thrown.
What actually happened? Please include the actual, raw output from ESLint.
No error was thrown.
Are you willing to submit a pull request to fix this bug?
Happy to have a go if somebody can point me in the right direction :)
The text was updated successfully, but these errors were encountered: