Skip to content

Commit

Permalink
Update: improve null detection in eqeqeq for ES6 regexes (fixes #8020) (
Browse files Browse the repository at this point in the history
#8042)

* Update: improve null detection in eqeqeq for ES6 regexes (fixes #8020)

* Also update astUtils.isNullOrUndefined

* Check node.regex instead of node.raw
  • Loading branch information
not-an-aardvark committed Feb 11, 2017
1 parent 16248e2 commit 90fd555
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
19 changes: 18 additions & 1 deletion lib/ast-utils.js
Expand Up @@ -145,7 +145,7 @@ function isInLoop(node) {
*/
function isNullOrUndefined(node) {
return (
(node.type === "Literal" && node.value === null) ||
module.exports.isNullLiteral(node) ||
(node.type === "Identifier" && node.name === "undefined") ||
(node.type === "UnaryExpression" && node.operator === "void")
);
Expand Down Expand Up @@ -1284,5 +1284,22 @@ module.exports = {
default:
return false;
}
},

/**
* Determines whether the given node is a `null` literal.
* @param {ASTNode} node The node to check
* @returns {boolean} `true` if the node is a `null` literal
*/
isNullLiteral(node) {

/*
* Checking `node.value === null` does not guarantee that a literal is a null literal.
* When parsing values that cannot be represented in the current environment (e.g. unicode
* regexes in Node 4), `node.value` is set to `null` because it wouldn't be possible to
* set `node.value` to a unicode regex. To make sure a literal is actually `null`, check
* `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020
*/
return node.type === "Literal" && node.value === null && !node.regex;
}
};
9 changes: 7 additions & 2 deletions lib/rules/eqeqeq.js
Expand Up @@ -5,6 +5,12 @@

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("../ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -100,8 +106,7 @@ module.exports = {
* @private
*/
function isNullCheck(node) {
return (node.right.type === "Literal" && node.right.value === null) ||
(node.left.type === "Literal" && node.left.value === null);
return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left);
}

/**
Expand Down
22 changes: 22 additions & 0 deletions tests/lib/ast-utils.js
Expand Up @@ -171,6 +171,10 @@ describe("ast-utils", () => {
eslint.on("CallExpression", checker);
eslint.verify("foo.apply({}, a, b);", {}, filename, true);
});

it("should return false if it's a unicode regex", () => {
assert.isFalse(astUtils.isNullOrUndefined(espree.parse("/abc/u", { ecmaVersion: 6 }).body[0].expression));
});
});

describe("checkReference", () => {
Expand Down Expand Up @@ -1245,4 +1249,22 @@ describe("ast-utils", () => {
});
}

describe("isNullLiteral", () => {
const EXPECTED_RESULTS = {
null: true,
"/abc/u": false,
5: false,
true: false,
"'null'": false,
foo: false
};

Object.keys(EXPECTED_RESULTS).forEach(key => {
it(`returns ${EXPECTED_RESULTS[key]} for ${key}`, () => {
const ast = espree.parse(key, { ecmaVersion: 6 });

assert.strictEqual(astUtils.isNullLiteral(ast.body[0].expression), EXPECTED_RESULTS[key]);
});
});
});
});
5 changes: 4 additions & 1 deletion tests/lib/rules/eqeqeq.js
Expand Up @@ -42,7 +42,10 @@ ruleTester.run("eqeqeq", rule, {
{ code: "a == null", options: ["always", { null: "never" }] },
{ code: "a != null", options: ["always", { null: "never" }] },
{ code: "null == null", options: ["always", { null: "never" }] },
{ code: "null != null", options: ["always", { null: "never" }] }
{ code: "null != null", options: ["always", { null: "never" }] },

// https://github.com/eslint/eslint/issues/8020
{ code: "foo === /abc/u", options: ["always", { null: "never" }], parserOptions: { ecmaVersion: 6 } }
],
invalid: [
{ code: "a == b", errors: [{ message: "Expected '===' and instead saw '=='.", type: "BinaryExpression" }] },
Expand Down

0 comments on commit 90fd555

Please sign in to comment.