-
-
Notifications
You must be signed in to change notification settings - Fork 171
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
Allows this
in EventEmitter
's callbacks (no-invalid-this
)
#4
Labels
Comments
Made quick & dirty change to /**
* @fileoverview A rule to disallow `this` keywords outside of classes or class-like objects.
* @author Toru Nagashima
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow `this` keywords outside of classes or class-like objects",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/no-invalid-this"
},
schema: [
{
type: "object",
properties: {
capIsConstructor: {
type: "boolean",
default: true
}
},
additionalProperties: false
}
],
messages: {
unexpectedThis: "Unexpected 'this'."
}
},
create(context) {
const options = context.options[0] || {};
const capIsConstructor = options.capIsConstructor !== false;
const stack = [],
sourceCode = context.getSourceCode();
/**
* Gets the current checking context.
*
* The return value has a flag that whether or not `this` keyword is valid.
* The flag is initialized when got at the first time.
* @returns {{valid: boolean}}
* an object which has a flag that whether or not `this` keyword is valid.
*/
stack.getCurrent = function() {
const current = this[this.length - 1];
if (!current.init) {
current.init = true;
current.valid = !astUtils.isDefaultThisBinding(
current.node,
sourceCode,
{ capIsConstructor }
) || isListener(current.node);
}
return current;
};
/**
* Checks if function node is used in NodeJS listener addition.
* @param {ASTNode} node A function node
* @returns {boolean} A function node is used in NodeJS listener addition.
*/
function isListener(node)
{
const listenersArray = ["on", "once", "addListener", "prependListener", "prependOnceListener"];
if (node.type !== "FunctionExpression") return false;
if (!node.parent || node.parent.type !== "CallExpression") return false;
const callee = node.parent.callee;
if (!callee || callee.type !== "MemberExpression") return false;
return (listenersArray.indexOf(callee.property.name) != -1);
}
/**
* Pushs new checking context into the stack.
*
* The checking context is not initialized yet.
* Because most functions don't have `this` keyword.
* When `this` keyword was found, the checking context is initialized.
* @param {ASTNode} node A function node that was entered.
* @returns {void}
*/
function enterFunction(node) {
// `this` can be invalid only under strict mode.
stack.push({
init: !context.getScope().isStrict,
node,
valid: true
});
}
/**
* Pops the current checking context from the stack.
* @returns {void}
*/
function exitFunction() {
stack.pop();
}
return {
/*
* `this` is invalid only under strict mode.
* Modules is always strict mode.
*/
Program(node) {
const scope = context.getScope(),
features = context.parserOptions.ecmaFeatures || {};
stack.push({
init: true,
node,
valid: !(
scope.isStrict ||
node.sourceType === "module" ||
(features.globalReturn && scope.childScopes[0].isStrict)
)
});
},
"Program:exit"() {
stack.pop();
},
FunctionDeclaration: enterFunction,
"FunctionDeclaration:exit": exitFunction,
FunctionExpression: enterFunction,
"FunctionExpression:exit": exitFunction,
// Reports if `this` of the current context is invalid.
ThisExpression(node) {
const current = stack.getCurrent();
if (current && !current.valid) {
context.report({
node,
messageId: "unexpectedThis"
});
}
}
};
}
}; |
Reworked this rule along with several others to use as custom rule set in https://github.com/Antonius-S/ESLint-custom-rules |
nazrhyn
pushed a commit
to nazrhyn/eslint-plugin-node
that referenced
this issue
Mar 23, 2022
* add support for Node.js ESM resolution * Update lib/rules/no-hide-core-modules.js Co-authored-by: 唯然 <weiran.zsd@outlook.com> * Update lib/util/import-target.js * invalidate ESM imports that were valid in Node 10 * Update scripts/update.js Co-authored-by: 唯然 <weiran.zsd@outlook.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No description provided.
The text was updated successfully, but these errors were encountered: