β¬ οΈ Back to Table of Contents
π no-implied-eval¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 6 |
| π¦ Imports | 6 |
| π Variables & Constants | 3 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/no-implied-eval.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'no-implied-eval' |
meta.type |
'suggestion' |
meta.docs.description |
'Disallow the use of eval()-like functions' |
meta.docs.extendsBaseRule |
true |
meta.docs.recommended |
'recommended' |
meta.docs.requiresTypeChecking |
true |
meta.messages.noFunctionConstructor |
'Implied eval. Do not use the Function constructor to create functions.' |
meta.messages.noImpliedEvalError |
'Implied eval. Consider passing a function.' |
meta.schema |
[] |
defaultOptions |
[] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
getParserServices |
../util |
isBuiltinSymbolLike |
../util |
isReferenceToGlobalFunction |
../util |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
FUNCTION_CONSTRUCTOR |
"Function" |
const | 'Function' |
β |
GLOBAL_CANDIDATES |
Set<string> |
const | new Set(['global', 'globalThis', 'window']) |
β |
EVAL_LIKE_FUNCTIONS |
Set<string> |
const | new Set([ 'execScript', 'setImmediate', 'setInterval', 'setTimeout', ]) |
β |
Functions¶
create(context: any): { CallExpression: (node: TSESTree.CallExpression | TSESTree⦶
Parameters:
contextany
Returns: { CallExpression: (node: TSESTree.CallExpression | TSESTree.NewExpression) => void; NewExpression: (node: TSESTree.CallExpression | TSESTree.NewExpression) => void; }
Calls:
getParserServices (from ../util)services.program.getTypeCheckerGLOBAL_CANDIDATES.hasservices.getTypeAtLocationtype.getSymboltsutils.isSymbolFlagSetisBuiltinSymbolLike (from ../util)checker.getSignaturesOfTypeisBindisFunctionTypegetCalleeNamecontext.reportEVAL_LIKE_FUNCTIONS.hasisFunctionisReferenceToGlobalFunction (from ../util)
Code
create(context) {
const services = getParserServices(context);
const checker = services.program.getTypeChecker();
function getCalleeName(node: TSESTree.Expression): string | null {
if (node.type === AST_NODE_TYPES.Identifier) {
return node.name;
}
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.object.type === AST_NODE_TYPES.Identifier &&
GLOBAL_CANDIDATES.has(node.object.name)
) {
if (node.property.type === AST_NODE_TYPES.Identifier) {
return node.property.name;
}
if (
node.property.type === AST_NODE_TYPES.Literal &&
typeof node.property.value === 'string'
) {
return node.property.value;
}
}
return null;
}
function isFunctionType(node: TSESTree.Node): boolean {
const type = services.getTypeAtLocation(node);
const symbol = type.getSymbol();
if (
symbol &&
tsutils.isSymbolFlagSet(
symbol,
ts.SymbolFlags.Function | ts.SymbolFlags.Method,
)
) {
return true;
}
if (isBuiltinSymbolLike(services.program, type, FUNCTION_CONSTRUCTOR)) {
return true;
}
const signatures = checker.getSignaturesOfType(
type,
ts.SignatureKind.Call,
);
return signatures.length > 0;
}
function isBind(node: TSESTree.Node): boolean {
return node.type === AST_NODE_TYPES.MemberExpression
? isBind(node.property)
: node.type === AST_NODE_TYPES.Identifier && node.name === 'bind';
}
function isFunction(node: TSESTree.Node): boolean {
switch (node.type) {
case AST_NODE_TYPES.ArrowFunctionExpression:
case AST_NODE_TYPES.FunctionDeclaration:
case AST_NODE_TYPES.FunctionExpression:
return true;
case AST_NODE_TYPES.Literal:
case AST_NODE_TYPES.TemplateLiteral:
return false;
case AST_NODE_TYPES.CallExpression:
return isBind(node.callee) || isFunctionType(node);
default:
return isFunctionType(node);
}
}
function checkImpliedEval(
node: TSESTree.CallExpression | TSESTree.NewExpression,
): void {
const calleeName = getCalleeName(node.callee);
if (calleeName == null) {
return;
}
if (calleeName === FUNCTION_CONSTRUCTOR) {
const type = services.getTypeAtLocation(node.callee);
const symbol = type.getSymbol();
if (symbol) {
if (
isBuiltinSymbolLike(services.program, type, 'FunctionConstructor')
) {
context.report({ node, messageId: 'noFunctionConstructor' });
return;
}
} else {
context.report({ node, messageId: 'noFunctionConstructor' });
return;
}
}
if (node.arguments.length === 0) {
return;
}
const [handler] = node.arguments;
if (
EVAL_LIKE_FUNCTIONS.has(calleeName) &&
!isFunction(handler) &&
isReferenceToGlobalFunction(calleeName, node, context.sourceCode)
) {
context.report({ node: handler, messageId: 'noImpliedEvalError' });
}
}
return {
CallExpression: checkImpliedEval,
NewExpression: checkImpliedEval,
};
}
Internal helpers¶
Declared inside another function in this file.
getCalleeName(node: TSESTree.Expression): string | null¶
Parameters:
nodeTSESTree.Expression
Returns: string | null
Calls:
GLOBAL_CANDIDATES.has
Code
function getCalleeName(node: TSESTree.Expression): string | null {
if (node.type === AST_NODE_TYPES.Identifier) {
return node.name;
}
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.object.type === AST_NODE_TYPES.Identifier &&
GLOBAL_CANDIDATES.has(node.object.name)
) {
if (node.property.type === AST_NODE_TYPES.Identifier) {
return node.property.name;
}
if (
node.property.type === AST_NODE_TYPES.Literal &&
typeof node.property.value === 'string'
) {
return node.property.value;
}
}
return null;
}
isFunctionType(node: TSESTree.Node): boolean¶
Parameters:
nodeTSESTree.Node
Returns: boolean
Calls:
services.getTypeAtLocationtype.getSymboltsutils.isSymbolFlagSetisBuiltinSymbolLike (from ../util)checker.getSignaturesOfType
Code
function isFunctionType(node: TSESTree.Node): boolean {
const type = services.getTypeAtLocation(node);
const symbol = type.getSymbol();
if (
symbol &&
tsutils.isSymbolFlagSet(
symbol,
ts.SymbolFlags.Function | ts.SymbolFlags.Method,
)
) {
return true;
}
if (isBuiltinSymbolLike(services.program, type, FUNCTION_CONSTRUCTOR)) {
return true;
}
const signatures = checker.getSignaturesOfType(
type,
ts.SignatureKind.Call,
);
return signatures.length > 0;
}
isBind(node: TSESTree.Node): boolean¶
Parameters:
nodeTSESTree.Node
Returns: boolean
Calls:
isBind
Code
isFunction(node: TSESTree.Node): boolean¶
Parameters:
nodeTSESTree.Node
Returns: boolean
Calls:
isBindisFunctionType
Code
function isFunction(node: TSESTree.Node): boolean {
switch (node.type) {
case AST_NODE_TYPES.ArrowFunctionExpression:
case AST_NODE_TYPES.FunctionDeclaration:
case AST_NODE_TYPES.FunctionExpression:
return true;
case AST_NODE_TYPES.Literal:
case AST_NODE_TYPES.TemplateLiteral:
return false;
case AST_NODE_TYPES.CallExpression:
return isBind(node.callee) || isFunctionType(node);
default:
return isFunctionType(node);
}
}
checkImpliedEval(node: TSESTree.CallExpression | TSESTree.NewEβ¦): void¶
Parameters:
nodeTSESTree.CallExpression | TSESTree.NewExpression
Returns: void
Calls:
getCalleeNameservices.getTypeAtLocationtype.getSymbolisBuiltinSymbolLike (from ../util)context.reportEVAL_LIKE_FUNCTIONS.hasisFunctionisReferenceToGlobalFunction (from ../util)
Code
function checkImpliedEval(
node: TSESTree.CallExpression | TSESTree.NewExpression,
): void {
const calleeName = getCalleeName(node.callee);
if (calleeName == null) {
return;
}
if (calleeName === FUNCTION_CONSTRUCTOR) {
const type = services.getTypeAtLocation(node.callee);
const symbol = type.getSymbol();
if (symbol) {
if (
isBuiltinSymbolLike(services.program, type, 'FunctionConstructor')
) {
context.report({ node, messageId: 'noFunctionConstructor' });
return;
}
} else {
context.report({ node, messageId: 'noFunctionConstructor' });
return;
}
}
if (node.arguments.length === 0) {
return;
}
const [handler] = node.arguments;
if (
EVAL_LIKE_FUNCTIONS.has(calleeName) &&
!isFunction(handler) &&
isReferenceToGlobalFunction(calleeName, node, context.sourceCode)
) {
context.report({ node: handler, messageId: 'noImpliedEvalError' });
}
}
Generated by Syntax Scribe