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

False negatives in 3 rules when right side of && expression is a literal #13634

Closed
btmills opened this issue Aug 30, 2020 · 1 comment
Closed
Assignees
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion rule Relates to ESLint's core rules

Comments

@btmills
Copy link
Member

btmills commented Aug 30, 2020

Tell us about your environment

  • ESLint Version: 7.7.0
  • Node Version: 14.9.0
  • npm Version: 6.14.7

What parser (default, @babel/eslint-parser, @typescript-eslint/parser, etc.) are you using?

default

Please show your full configuration:

Configuration
module.exports = {
    parserOptions: {
        ecmaVersion: 2020
    }
};

What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.

/* eslint constructor-super: "error",
   no-throw-literal: "error",
   prefer-promise-reject-errors: "error"
 */
let anything;

// If anything is a constructor, it'll be truthy, we'll evaluate the
// right side of the &&, and we'll extend 42.
class Subclass extends (anything && 42) {
    constructor() {
        super();
    }
}

// If anything is an Error instance, it'll be truthy, we'll evaluate
// the right side of the &&, and we'll throw 42.
throw anything && 42;

// If anything is an Error instance, it'll be truthy, we'll evaluate
// the right side of the &&, and we'll reject with 42.
Promise.reject(anything && 5);

Demo

What did you expect to happen?

We should report errors in each of the above cases. All three are looking for a specific type of truthy value from the expression. Because the expression uses &&, any possibly-valid value would evaluate to the right side of the expression, which would not be a valid value in these examples.

This was originally discovered in #13618 (comment). Because it relates to existing behavior that existed prior to that pull request, we decided to split it into its own issue that can be fixed after the pull request is merged. This bug is a false negative in the 3 rules above, and fixing it would cause them to report more errors. Does anyone object to fixing this in a semver-minor change as allowed by our semver policy?

The fix would update both astUtils.couldBeError() and constructor-super's isPossibleConstructor() to only check the right side of && LogicalExpressions.

What actually happened? Please include the actual, raw output from ESLint.

No errors are reported.

Are you willing to submit a pull request to fix this bug?

Yes, if @mdjermanovic doesn't get to it first.

@btmills btmills added bug ESLint is working incorrectly rule Relates to ESLint's core rules core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion labels Aug 30, 2020
@btmills btmills self-assigned this Aug 30, 2020
@mdjermanovic
Copy link
Member

I support fixing this in a semver-minor change.

btmills added a commit that referenced this issue Oct 18, 2020
When `constructor-super`, `no-throw-literal`, and
`prefer-promise-reject-errors` are looking for plausible constructor or
error values, they fail to consider the short-circuiting behavior
differences between the `&&` and `||` operators. This results in a false
negative where these rules allow `foo && 42` when that expression cannot
be a constructor or error. If the left side is falsy, the expression
short-circuits with the falsy value. If the left side is truthy, the
result of the expression is the right side value. All three rules
already report the right side value in isolation but currently
incorrectly allow it when on the right side of an `&&` expression.

When @mdjermanovic added support for logical assignment operators, we
decided to ship with the corrected behavior for `&&=` by only checking
the right side of the expression, accepting that treatment of `&&=`
would be inconsistent with existing treatment of `&&`. This PR then
fixes the `&&` treatment in what we believe can be a semver-minor bug
fix.

A future improvement could detect statically falsy values on the left
side of `&&` expressions and report those as well. Such a change could
also update the `||` treatment to ignore plausibly-(constructor|error)
values on the right side if the left side is statically truthy but not
plausibly a constructor or error, so `42 || foo` should fail.
@eslint-github-bot eslint-github-bot bot locked and limited conversation to collaborators Apr 21, 2021
@eslint-github-bot eslint-github-bot bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Apr 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly core Relates to ESLint's core APIs and features evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion rule Relates to ESLint's core rules
Projects
None yet
Development

No branches or pull requests

2 participants