Created
January 6, 2025 09:14
Eslint-plugin-react-perf v3.3.3 - huynhducduy's PRs Patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/utils/common.js b/lib/utils/common.js | |
index 90415975e33ea77d161df0329d3ed2426977c404..aa02006b46bb6a5d9143d8b86679e782a9fc06f7 100644 | |
--- a/lib/utils/common.js | |
+++ b/lib/utils/common.js | |
@@ -1,11 +1,14 @@ | |
-"use strict"; | |
+'use strict' | |
+ | |
+const {get} = require('http') | |
+const {type} = require('os') | |
function createRule(description, errorMessage, isViolation) { | |
return { | |
meta: { | |
docs: { | |
description, | |
- category: "", | |
+ category: '', | |
recommended: true, | |
}, | |
schema: [ | |
@@ -15,128 +18,229 @@ function createRule(description, errorMessage, isViolation) { | |
nativeAllowList: { | |
oneOf: [ | |
{ | |
- enum: ["all"], | |
+ enum: ['all'], | |
}, | |
{ | |
- type: "array", | |
+ type: 'array', | |
items: { | |
- type: "string", | |
+ type: 'string', | |
}, | |
}, | |
], | |
}, | |
+ allowList: { | |
+ type: 'array', | |
+ items: { | |
+ type: 'string', | |
+ }, | |
+ }, | |
+ ignoreComponents: { | |
+ type: 'array', | |
+ items: { | |
+ type: 'string', | |
+ }, | |
+ }, | |
+ ignoreSources: { | |
+ type: 'array', | |
+ items: { | |
+ oneOf: [ | |
+ {type: 'string'}, | |
+ { | |
+ type: 'object', | |
+ properties: { | |
+ source: { | |
+ type: 'string', | |
+ }, | |
+ importNames: { | |
+ type: 'array', | |
+ items: { | |
+ type: 'string', | |
+ }, | |
+ }, | |
+ }, | |
+ additionalProperties: false, | |
+ }, | |
+ ], | |
+ }, | |
+ }, | |
}, | |
- type: "object", | |
+ type: 'object', | |
}, | |
], | |
}, | |
create: function (context) { | |
- const { options } = context; | |
- const { nativeAllowList } = options[0] || {}; | |
+ const {options} = context | |
+ const {nativeAllowList, allowList, ignoreComponents, ignoreSources} = options[0] || {} | |
+ | |
+ const allowListSet = new Set() | |
+ | |
+ if (allowList) { | |
+ allowList.forEach(item => { | |
+ allowListSet.add(item) | |
+ }) | |
+ } | |
+ | |
+ const sourceMap = new Map() | |
+ const ignoreComponentsSet = new Set() | |
+ | |
+ if (ignoreComponents) { | |
+ ignoreComponents.forEach(component => { | |
+ ignoreComponentsSet.add(component) | |
+ }) | |
+ } | |
+ | |
+ const ignoreSourcesSet = new Set() | |
+ | |
+ if (ignoreSources) { | |
+ ignoreSources.forEach(config => { | |
+ if (typeof config === 'string') { | |
+ ignoreSourcesSet.add(config) | |
+ } else { | |
+ config.importNames.forEach(importName => { | |
+ ignoreSourcesSet.add(hashSourceAndImportName(config.source, importName)) | |
+ }) | |
+ } | |
+ }) | |
+ } | |
+ | |
return { | |
+ ImportDeclaration: function (node) { | |
+ node.specifiers.forEach(specifier => { | |
+ if (specifier.type === 'ImportSpecifier') { | |
+ sourceMap.set(specifier.local.name, [node.source.value, specifier.imported.name]) | |
+ } else if (specifier.type === 'ImportDefaultSpecifier') { | |
+ sourceMap.set(specifier.local.name, [node.source.value, 'default']) | |
+ } | |
+ }) | |
+ }, | |
JSXAttribute: function (node) { | |
- if (!node.value || node.value.type !== "JSXExpressionContainer") { | |
- return; | |
+ if (!node.value || node.value.type !== 'JSXExpressionContainer') { | |
+ return | |
} | |
+ | |
if ( | |
isNativeElement(node) && | |
- (nativeAllowList === "all" || | |
+ (nativeAllowList === 'all' || | |
(Array.isArray(nativeAllowList) && | |
nativeAllowList.find(function (nativeExclude) { | |
- return ( | |
- node.name.name.toLowerCase() === nativeExclude.toLowerCase() | |
- ); | |
+ return node.name.name.toLowerCase() === nativeExclude.toLowerCase() | |
}))) | |
) { | |
- return; | |
+ return | |
} | |
- var violationFound = false; | |
- findRelevantNodes(context, node.value.expression).forEach(function ( | |
- node | |
- ) { | |
+ if (allowListSet.has(node.name.name)) { | |
+ return | |
+ } | |
+ | |
+ if (ignoreComponentsSet.has(node.parent.name.name)) { | |
+ return | |
+ } | |
+ | |
+ if (ignoreSources) { | |
+ let source | |
+ if (node.parent.name.type === 'JSXMemberExpression') { | |
+ const object = node.parent.name.object.name | |
+ const property = node.parent.name.property.name | |
+ const realSource = sourceMap.get(object) | |
+ | |
+ if (realSource) { source = [realSource[0], property] } | |
+ } else { | |
+ source = sourceMap.get(node.parent.name.name) | |
+ } | |
+ | |
+ if ( | |
+ source && | |
+ (ignoreSourcesSet.has(source[0]) || | |
+ ignoreSourcesSet.has(hashSourceAndImportName(source[0], source[1]))) | |
+ ) { | |
+ return | |
+ } | |
+ } | |
+ | |
+ var violationFound = false | |
+ findRelevantNodes(context, node.value.expression).forEach(function (node) { | |
if (isViolation(node)) { | |
- violationFound = true; | |
- context.report(node, errorMessage); | |
+ violationFound = true | |
+ context.report(node, errorMessage) | |
} | |
- }); | |
- return violationFound; | |
+ }) | |
+ return violationFound | |
}, | |
- }; | |
+ } | |
}, | |
- }; | |
+ } | |
} | |
function findRelevantNodes(context, node) { | |
function _findRelevantNodes(node) { | |
- if (node.type === "Literal") { | |
+ if (node.type === 'Literal') { | |
// we have found a Literal (ex. 'foo', 1, false), bail | |
- return; | |
+ return | |
} | |
- if (node.type === "Identifier") { | |
- const sourceCode = context.sourceCode || context.getSourceCode(); | |
- const scope = sourceCode.getScope | |
- ? sourceCode.getScope(node) | |
- : context.getScope(); | |
+ if (node.type === 'Identifier') { | |
+ const sourceCode = context.sourceCode || context.getSourceCode() | |
+ const scope = sourceCode.getScope ? sourceCode.getScope(node) : context.getScope() | |
var variable = scope.variables.find(function (variable) { | |
- return variable.name === node.name; | |
- }); | |
+ return variable.name === node.name | |
+ }) | |
if (variable) { | |
variable.references.forEach(function (reference) { | |
- if (!reference.identifier.parent) return; | |
+ if (!reference.identifier.parent) return | |
switch (reference.identifier.parent.type) { | |
- case "AssignmentExpression": | |
- nodes.push(reference.identifier.parent.right); | |
- break; | |
- case "VariableDeclarator": | |
- nodes.push(reference.identifier.parent.init); | |
- break; | |
- case "AssignmentPattern": | |
- nodes.push(reference.identifier.parent.right); | |
- break; | |
+ case 'AssignmentExpression': | |
+ nodes.push(reference.identifier.parent.right) | |
+ break | |
+ case 'VariableDeclarator': | |
+ nodes.push(reference.identifier.parent.init) | |
+ break | |
+ case 'AssignmentPattern': | |
+ nodes.push(reference.identifier.parent.right) | |
+ break | |
} | |
- }); | |
+ }) | |
} | |
- return; | |
+ return | |
} | |
- if (node.type === "LogicalExpression") { | |
- return _findRelevantNodes(node.left) || _findRelevantNodes(node.right); | |
+ if (node.type === 'LogicalExpression') { | |
+ return _findRelevantNodes(node.left) || _findRelevantNodes(node.right) | |
} | |
- if (node.type === "ConditionalExpression") { | |
- return ( | |
- _findRelevantNodes(node.consequent) || | |
- _findRelevantNodes(node.alternate) | |
- ); | |
+ if (node.type === 'ConditionalExpression') { | |
+ return _findRelevantNodes(node.consequent) || _findRelevantNodes(node.alternate) | |
} | |
- nodes.push(node); | |
+ nodes.push(node) | |
} | |
- var nodes = []; | |
- _findRelevantNodes(node); | |
- return nodes; | |
+ var nodes = [] | |
+ _findRelevantNodes(node) | |
+ return nodes | |
} | |
function checkConstructor(node, className) { | |
if (node.callee && node.callee.name === className) { | |
- if (["NewExpression", "CallExpression"].indexOf(node.type) !== -1) { | |
- return true; | |
+ if (['NewExpression', 'CallExpression'].indexOf(node.type) !== -1) { | |
+ return true | |
} | |
} | |
} | |
function isNativeElement(node) { | |
- if (node.parent.name.type !== "JSXIdentifier") { | |
- return false; | |
+ if (node.parent.name.type !== 'JSXIdentifier') { | |
+ return false | |
} | |
- const nodeName = node.parent.name.name; | |
- const firstChar = nodeName.charAt(0); | |
- return firstChar === firstChar.toLowerCase(); | |
+ const nodeName = node.parent.name.name | |
+ const firstChar = nodeName.charAt(0) | |
+ return firstChar === firstChar.toLowerCase() | |
+} | |
+ | |
+function hashSourceAndImportName(source, importName) { | |
+ return source + '%%%' + importName | |
} | |
module.exports = { | |
createRule, | |
checkConstructor, | |
-}; | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment