oxlint-plugin-react-doctor 0.7.5-dev.21da48f → 0.7.5-dev.3075e10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -62
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5178,10 +5178,8 @@ const STORAGE_GLOBALS = new Set([
|
|
|
5178
5178
|
const SENSITIVE_KEY_PATTERN = /token|jwt|secret|password|passwd|credential|api[-_]?key|bearer|private[-_]?key/i;
|
|
5179
5179
|
const NON_AUTH_TOKEN_PATTERN = /csrf|xsrf|device|fcm|apns|push|design|tokeniz|syntax|css|theme|color/i;
|
|
5180
5180
|
const STRONG_AUTH_KEY_PATTERN = /jwt|secret|password|passwd|credential|private[-_]?key|api[-_]?key|bearer|access[-_]?token|refresh[-_]?token|auth[-_]?token|id[-_]?token|session/i;
|
|
5181
|
-
const PRODUCT_API_KEY_RECORDS_PATTERN = /(?:^|[._:-])(?:created|saved|integration|mailing)[-_]?api[-_]?keys$/i;
|
|
5182
5181
|
const PRODUCT_API_KEY_COLLECTION_PATTERN = /[._:-](?:created|generated|saved)[-_]?api[-_]?keys$/i;
|
|
5183
5182
|
const isAuthCredentialKey = (key) => {
|
|
5184
|
-
if (PRODUCT_API_KEY_RECORDS_PATTERN.test(key)) return false;
|
|
5185
5183
|
if (!SENSITIVE_KEY_PATTERN.test(key)) return false;
|
|
5186
5184
|
if (PRODUCT_API_KEY_COLLECTION_PATTERN.test(key)) return false;
|
|
5187
5185
|
if (NON_AUTH_TOKEN_PATTERN.test(key) && !STRONG_AUTH_KEY_PATTERN.test(key)) return false;
|
|
@@ -24000,26 +23998,6 @@ const STATEFUL_HTML_DESCENDANT_TAGS = new Set([
|
|
|
24000
23998
|
"dialog",
|
|
24001
23999
|
"canvas"
|
|
24002
24000
|
]);
|
|
24003
|
-
const STATEFUL_HTML_ATTRIBUTE_NAMES = new Set([
|
|
24004
|
-
"autofocus",
|
|
24005
|
-
"contenteditable",
|
|
24006
|
-
"draggable",
|
|
24007
|
-
"tabindex"
|
|
24008
|
-
]);
|
|
24009
|
-
const isStaticallyFalseAttributeValue = (attribute) => {
|
|
24010
|
-
if (!isNodeOfType(attribute, "JSXAttribute") || !attribute.value) return false;
|
|
24011
|
-
const value = isNodeOfType(attribute.value, "JSXExpressionContainer") ? attribute.value.expression : attribute.value;
|
|
24012
|
-
return isNodeOfType(value, "Literal") && (value.value === false || value.value === "false");
|
|
24013
|
-
};
|
|
24014
|
-
const hasStatefulHtmlAttribute = (openingElement) => {
|
|
24015
|
-
if (!isNodeOfType(openingElement, "JSXOpeningElement")) return false;
|
|
24016
|
-
return openingElement.attributes.some((attribute) => {
|
|
24017
|
-
if (!isNodeOfType(attribute, "JSXAttribute") || !isNodeOfType(attribute.name, "JSXIdentifier")) return false;
|
|
24018
|
-
const attributeName = attribute.name.name.toLowerCase();
|
|
24019
|
-
if (!STATEFUL_HTML_ATTRIBUTE_NAMES.has(attributeName)) return false;
|
|
24020
|
-
return attributeName === "tabindex" || !isStaticallyFalseAttributeValue(attribute);
|
|
24021
|
-
});
|
|
24022
|
-
};
|
|
24023
24001
|
const STATEFUL_DESCENDANT_SCAN_BUDGET = 200;
|
|
24024
24002
|
const rootIdentifierNameOf = (expression) => {
|
|
24025
24003
|
let object = expression;
|
|
@@ -24037,8 +24015,7 @@ const containsStatefulDescendant = (jsxElement, options = {}) => {
|
|
|
24037
24015
|
budget -= 1;
|
|
24038
24016
|
const node = stack.pop();
|
|
24039
24017
|
if (isNodeOfType(node, "JSXElement")) {
|
|
24040
|
-
const
|
|
24041
|
-
const name = opening.name;
|
|
24018
|
+
const name = node.openingElement.name;
|
|
24042
24019
|
if (name && isNodeOfType(name, "JSXIdentifier")) {
|
|
24043
24020
|
const tagName = name.name;
|
|
24044
24021
|
const firstChar = tagName.charCodeAt(0);
|
|
@@ -24046,7 +24023,6 @@ const containsStatefulDescendant = (jsxElement, options = {}) => {
|
|
|
24046
24023
|
if (STATEFUL_HTML_DESCENDANT_TAGS.has(tagName)) return true;
|
|
24047
24024
|
}
|
|
24048
24025
|
if (name && isNodeOfType(name, "JSXMemberExpression")) return true;
|
|
24049
|
-
if (hasStatefulHtmlAttribute(opening)) return true;
|
|
24050
24026
|
const children = node.children ?? [];
|
|
24051
24027
|
for (const child of children) stack.push(child);
|
|
24052
24028
|
continue;
|
|
@@ -24606,14 +24582,6 @@ const templateHasOuterMemberIdentity = (template, bindingFunction) => {
|
|
|
24606
24582
|
}
|
|
24607
24583
|
return false;
|
|
24608
24584
|
};
|
|
24609
|
-
const findBareItemNamesReferencedByTemplate = (template, itemNames) => {
|
|
24610
|
-
const referencedItemNames = /* @__PURE__ */ new Set();
|
|
24611
|
-
for (const expression of template.expressions ?? []) {
|
|
24612
|
-
const unwrappedExpression = stripParenExpression(expression);
|
|
24613
|
-
if (isNodeOfType(unwrappedExpression, "Identifier") && itemNames.has(unwrappedExpression.name)) referencedItemNames.add(unwrappedExpression.name);
|
|
24614
|
-
}
|
|
24615
|
-
return referencedItemNames;
|
|
24616
|
-
};
|
|
24617
24585
|
const forLoopTestReadsDataLength = (test) => {
|
|
24618
24586
|
let didFindLengthRead = false;
|
|
24619
24587
|
walkAst(test, (child) => {
|
|
@@ -24750,11 +24718,9 @@ const noArrayIndexAsKey = defineRule({
|
|
|
24750
24718
|
} else if (STATELESS_HTML_LEAF_TAGS.has(elementName.name)) {
|
|
24751
24719
|
const jsxElement = openingElement.parent;
|
|
24752
24720
|
if (jsxElement && isNodeOfType(jsxElement, "JSXElement")) {
|
|
24753
|
-
const isInlineTextRun = INLINE_TEXT_LEAF_TAGS.has(elementName.name);
|
|
24754
|
-
const primitiveItemNames = keyTemplate ? findBareItemNamesReferencedByTemplate(keyTemplate, itemNames) : EMPTY_NAME_SET;
|
|
24755
24721
|
if (!containsStatefulDescendant(jsxElement, {
|
|
24756
|
-
memberRootNames:
|
|
24757
|
-
bareIdentifierNames:
|
|
24722
|
+
memberRootNames: INLINE_TEXT_LEAF_TAGS.has(elementName.name) ? itemNames : EMPTY_NAME_SET,
|
|
24723
|
+
bareIdentifierNames: derivedNames
|
|
24758
24724
|
})) return;
|
|
24759
24725
|
}
|
|
24760
24726
|
}
|
|
@@ -35051,30 +35017,6 @@ const guardsRenderShape = (comparison) => {
|
|
|
35051
35017
|
}
|
|
35052
35018
|
return false;
|
|
35053
35019
|
};
|
|
35054
|
-
const isPropsChildrenLength = (node, scopes) => {
|
|
35055
|
-
const unwrappedNode = stripParenExpression(node);
|
|
35056
|
-
return isNodeOfType(unwrappedNode, "MemberExpression") && !unwrappedNode.computed && isNodeOfType(unwrappedNode.property, "Identifier") && unwrappedNode.property.name === "length" && resolvesToPropsChildren(stripParenExpression(unwrappedNode.object), scopes);
|
|
35057
|
-
};
|
|
35058
|
-
const isLargeTextLengthComparison = (node, scopes) => {
|
|
35059
|
-
const unwrappedNode = stripParenExpression(node);
|
|
35060
|
-
if (!isNodeOfType(unwrappedNode, "BinaryExpression")) return false;
|
|
35061
|
-
const leftIsLength = isPropsChildrenLength(unwrappedNode.left, scopes);
|
|
35062
|
-
const rightIsLength = isPropsChildrenLength(unwrappedNode.right, scopes);
|
|
35063
|
-
const thresholdNode = leftIsLength ? unwrappedNode.right : unwrappedNode.left;
|
|
35064
|
-
if (!leftIsLength && !rightIsLength || !isNodeOfType(thresholdNode, "Literal")) return false;
|
|
35065
|
-
if (typeof thresholdNode.value !== "number" || thresholdNode.value < 1e3) return false;
|
|
35066
|
-
return leftIsLength ? unwrappedNode.operator === ">" || unwrappedNode.operator === ">=" : unwrappedNode.operator === "<" || unwrappedNode.operator === "<=";
|
|
35067
|
-
};
|
|
35068
|
-
const isLargeStringOptimizationGuard = (comparison, scopes) => {
|
|
35069
|
-
let current = findTransparentExpressionRoot(comparison);
|
|
35070
|
-
while (current.parent) {
|
|
35071
|
-
const parent = current.parent;
|
|
35072
|
-
if (!isNodeOfType(parent, "LogicalExpression") || parent.operator !== "&&") return false;
|
|
35073
|
-
if (isLargeTextLengthComparison(parent.left === current ? parent.right : parent.left, scopes)) return true;
|
|
35074
|
-
current = findTransparentExpressionRoot(parent);
|
|
35075
|
-
}
|
|
35076
|
-
return false;
|
|
35077
|
-
};
|
|
35078
35020
|
const noPolymorphicChildren = defineRule({
|
|
35079
35021
|
id: "no-polymorphic-children",
|
|
35080
35022
|
title: "Children type checked at runtime",
|
|
@@ -35088,7 +35030,6 @@ const noPolymorphicChildren = defineRule({
|
|
|
35088
35030
|
const isStringLiteral = (operand) => isNodeOfType(operand, "Literal") && operand.value === "string";
|
|
35089
35031
|
if (!isStringLiteral(node.left) && !isStringLiteral(node.right)) return;
|
|
35090
35032
|
if (!guardsRenderShape(node)) return;
|
|
35091
|
-
if (isLargeStringOptimizationGuard(node, context.scopes)) return;
|
|
35092
35033
|
context.report({
|
|
35093
35034
|
node,
|
|
35094
35035
|
message: "Your users hit inconsistent behavior because `typeof children === \"string\"` makes this component switch on what callers pass, so add clear subcomponents like `<Button.Text>` instead."
|