From 4a2dd9830bcf2e54d1f95610269ed363a31ab188 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Mon, 21 Oct 2024 03:19:22 +0300 Subject: [PATCH 1/4] [Refactor] remove `array.prototype.flatmap` --- __tests__/__util__/helpers/parsers.js | 7 ++++--- __tests__/__util__/ruleOptionsMapperFactory.js | 4 +--- package.json | 1 - src/rules/alt-text.js | 7 ++----- src/rules/media-has-caption.js | 3 +-- src/util/isInteractiveElement.js | 16 +++------------- src/util/isInteractiveRole.js | 6 +----- src/util/isNonInteractiveElement.js | 16 +++------------- src/util/isNonInteractiveRole.js | 6 +----- 9 files changed, 16 insertions(+), 50 deletions(-) diff --git a/__tests__/__util__/helpers/parsers.js b/__tests__/__util__/helpers/parsers.js index 36753e913..7b2c78e28 100644 --- a/__tests__/__util__/helpers/parsers.js +++ b/__tests__/__util__/helpers/parsers.js @@ -1,7 +1,8 @@ import path from 'path'; import semver from 'semver'; import { version } from 'eslint/package.json'; -import flatMap from 'array.prototype.flatmap'; + +const { entries } = Object; let tsParserVersion; try { @@ -22,7 +23,7 @@ function minEcmaVersion(features, parserOptions) { const result = Math.max( ...[].concat( (parserOptions && parserOptions.ecmaVersion) || [], - flatMap(Object.entries(minEcmaVersionForFeatures), (entry) => { + entries(minEcmaVersionForFeatures).flatMap((entry) => { const f = entry[0]; const y = entry[1]; return features.has(f) ? y : []; @@ -68,7 +69,7 @@ const parsers = { }; }, all: function all(tests) { - const t = flatMap(tests, (test) => { + const t = tests.flatMap((test) => { /* eslint no-param-reassign: 0 */ if (typeof test === 'string') { test = { code: test }; diff --git a/__tests__/__util__/ruleOptionsMapperFactory.js b/__tests__/__util__/ruleOptionsMapperFactory.js index 0bdd26069..9b77f951b 100644 --- a/__tests__/__util__/ruleOptionsMapperFactory.js +++ b/__tests__/__util__/ruleOptionsMapperFactory.js @@ -2,8 +2,6 @@ * @flow */ -import flatMap from 'array.prototype.flatmap'; - const { fromEntries, entries } = Object; type ESLintTestRunnerTestCase = { @@ -25,7 +23,7 @@ export default function ruleOptionsMapperFactory(ruleOptions: Array = []) code, errors, // Flatten the array of objects in an array of one object. - options: [fromEntries(flatMap((options || []).concat(ruleOptions), (item) => entries(item)))], + options: [fromEntries((options || []).concat(ruleOptions).flatMap((item) => entries(item)))], parserOptions, settings, }; diff --git a/package.json b/package.json index 4fb4b4aca..f2022b986 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,6 @@ "license": "MIT", "dependencies": { "aria-query": "^5.3.2", - "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", diff --git a/src/rules/alt-text.js b/src/rules/alt-text.js index 49e436528..c4d0e777c 100644 --- a/src/rules/alt-text.js +++ b/src/rules/alt-text.js @@ -12,7 +12,6 @@ import { getPropValue, getLiteralPropValue, } from 'jsx-ast-utils'; -import flatMap from 'array.prototype.flatmap'; import { generateObjSchema, arraySchema } from '../util/schemas'; import getElementType from '../util/getElementType'; @@ -222,10 +221,8 @@ export default { // Elements to validate for alt text. const elementOptions = options.elements || DEFAULT_ELEMENTS; // Get custom components for just the elements that will be tested. - const customComponents = flatMap( - elementOptions, - (element) => options[element], - ); + const customComponents = elementOptions.flatMap((element) => options[element]); + const typesToValidate = new Set( [].concat( customComponents, diff --git a/src/rules/media-has-caption.js b/src/rules/media-has-caption.js index d20003deb..8e46fae31 100644 --- a/src/rules/media-has-caption.js +++ b/src/rules/media-has-caption.js @@ -10,7 +10,6 @@ import type { JSXElement, JSXOpeningElement, Node } from 'ast-types-flow'; import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; -import flatMap from 'array.prototype.flatmap'; import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; import { generateObjSchema, arraySchema } from '../util/schemas'; @@ -29,7 +28,7 @@ const schema = generateObjSchema({ const isMediaType = (context, type) => { const options = context.options[0] || {}; return MEDIA_TYPES - .concat(flatMap(MEDIA_TYPES, (mediaType) => options[mediaType])) + .concat(MEDIA_TYPES.flatMap((mediaType) => options[mediaType])) .some((typeToCheck) => typeToCheck === type); }; diff --git a/src/util/isInteractiveElement.js b/src/util/isInteractiveElement.js index cd0d69f56..9a2328ccf 100644 --- a/src/util/isInteractiveElement.js +++ b/src/util/isInteractiveElement.js @@ -11,7 +11,6 @@ import { AXObjects, elementAXObjects, } from 'axobject-query'; -import flatMap from 'array.prototype.flatmap'; import attributesComparator from './attributesComparator'; @@ -50,22 +49,13 @@ const interactiveRoles = new Set(roleKeys 'toolbar', )); -const interactiveElementRoleSchemas = flatMap( - elementRoleEntries, - ([elementSchema, rolesArr]) => (rolesArr.some((role): boolean => interactiveRoles.has(role)) ? [elementSchema] : []), -); +const interactiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSchema, rolesArr]) => (rolesArr.some((role): boolean => interactiveRoles.has(role)) ? [elementSchema] : [])); -const nonInteractiveElementRoleSchemas = flatMap( - elementRoleEntries, - ([elementSchema, rolesArr]) => (rolesArr.every((role): boolean => nonInteractiveRoles.has(role)) ? [elementSchema] : []), -); +const nonInteractiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSchema, rolesArr]) => (rolesArr.every((role): boolean => nonInteractiveRoles.has(role)) ? [elementSchema] : [])); const interactiveAXObjects = new Set(AXObjects.keys().filter((name) => AXObjects.get(name).type === 'widget')); -const interactiveElementAXObjectSchemas = flatMap( - [...elementAXObjects], - ([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => interactiveAXObjects.has(role)) ? [elementSchema] : []), -); +const interactiveElementAXObjectSchemas = [...elementAXObjects].flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => interactiveAXObjects.has(role)) ? [elementSchema] : [])); function checkIsInteractiveElement(tagName, attributes): boolean { function elementSchemaMatcher(elementSchema) { diff --git a/src/util/isInteractiveRole.js b/src/util/isInteractiveRole.js index a2c5ebadb..a55bbf66f 100644 --- a/src/util/isInteractiveRole.js +++ b/src/util/isInteractiveRole.js @@ -2,7 +2,6 @@ import { roles as rolesMap } from 'aria-query'; import type { Node } from 'ast-types-flow'; import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; -import flatMap from 'array.prototype.flatmap'; const roles = [...rolesMap.keys()]; const interactiveRoles = roles.filter((name) => ( @@ -39,10 +38,7 @@ const isInteractiveRole = ( let isInteractive = false; const normalizedValues = String(value).toLowerCase().split(' '); - const validRoles = flatMap( - normalizedValues, - (name: string) => (roles.includes(name) ? [name] : []), - ); + const validRoles = normalizedValues.flatMap((name) => (roles.includes(name) ? [name] : [])); if (validRoles.length > 0) { // The first role value is a series takes precedence. isInteractive = interactiveRoles.includes(validRoles[0]); diff --git a/src/util/isNonInteractiveElement.js b/src/util/isNonInteractiveElement.js index cdbf4c304..3cd17c3a1 100644 --- a/src/util/isNonInteractiveElement.js +++ b/src/util/isNonInteractiveElement.js @@ -12,7 +12,6 @@ import { elementAXObjects, } from 'axobject-query'; import type { Node } from 'ast-types-flow'; -import flatMap from 'array.prototype.flatmap'; import attributesComparator from './attributesComparator'; @@ -57,22 +56,13 @@ const interactiveRoles = new Set(roleKeys 'toolbar', )); -const interactiveElementRoleSchemas = flatMap( - elementRoleEntries, - ([elementSchema, rolesArr]) => (rolesArr.some((role): boolean => interactiveRoles.has(role)) ? [elementSchema] : []), -); +const interactiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSchema, rolesArr]) => (rolesArr.some((role): boolean => interactiveRoles.has(role)) ? [elementSchema] : [])); -const nonInteractiveElementRoleSchemas = flatMap( - elementRoleEntries, - ([elementSchema, rolesArr]) => (rolesArr.every((role): boolean => nonInteractiveRoles.has(role)) ? [elementSchema] : []), -); +const nonInteractiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSchema, rolesArr]) => (rolesArr.every((role): boolean => nonInteractiveRoles.has(role)) ? [elementSchema] : [])); const nonInteractiveAXObjects = new Set(AXObjects.keys().filter((name) => ['window', 'structure'].includes(AXObjects.get(name).type))); -const nonInteractiveElementAXObjectSchemas = flatMap( - [...elementAXObjects], - ([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : []), -); +const nonInteractiveElementAXObjectSchemas = [...elementAXObjects].flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [])); function checkIsNonInteractiveElement(tagName, attributes): boolean { function elementSchemaMatcher(elementSchema) { diff --git a/src/util/isNonInteractiveRole.js b/src/util/isNonInteractiveRole.js index 8132b54a1..a4992116f 100644 --- a/src/util/isNonInteractiveRole.js +++ b/src/util/isNonInteractiveRole.js @@ -8,7 +8,6 @@ import { } from 'aria-query'; import type { Node } from 'ast-types-flow'; import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; -import flatMap from 'array.prototype.flatmap'; const nonInteractiveRoles = [...rolesMap.keys()].filter((name) => ( !rolesMap.get(name).abstract @@ -47,10 +46,7 @@ const isNonInteractiveRole = ( let isNonInteractive = false; const normalizedValues = String(role).toLowerCase().split(' '); - const validRoles = flatMap( - normalizedValues, - (name: string) => (rolesMap.has(name) ? [name] : []), - ); + const validRoles = normalizedValues.flatMap((name: string) => (rolesMap.has(name) ? [name] : [])); if (validRoles.length > 0) { // The first role value is a series takes precedence. isNonInteractive = nonInteractiveRoles.includes(validRoles[0]); From 2314d08344464c73468d0783e74c371123fcbd21 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Mon, 21 Oct 2024 04:02:31 +0300 Subject: [PATCH 2/4] [Refactor] remove `hasown` --- package.json | 1 - src/rules/no-interactive-element-to-noninteractive-role.js | 3 ++- src/rules/no-noninteractive-element-interactions.js | 3 ++- src/rules/no-noninteractive-element-to-interactive-role.js | 3 ++- src/rules/no-redundant-roles.js | 3 ++- src/util/getElementType.js | 3 ++- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index f2022b986..e69ce7da7 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", - "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^10.0.1", diff --git a/src/rules/no-interactive-element-to-noninteractive-role.js b/src/rules/no-interactive-element-to-noninteractive-role.js index 2010ad9be..578f1fe78 100644 --- a/src/rules/no-interactive-element-to-noninteractive-role.js +++ b/src/rules/no-interactive-element-to-noninteractive-role.js @@ -16,7 +16,6 @@ import { propName, } from 'jsx-ast-utils'; import type { JSXIdentifier } from 'ast-types-flow'; -import hasOwn from 'hasown'; import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; import type { ESLintJSXAttribute } from '../../flow/eslint-jsx'; import getElementType from '../util/getElementType'; @@ -24,6 +23,8 @@ import isInteractiveElement from '../util/isInteractiveElement'; import isNonInteractiveRole from '../util/isNonInteractiveRole'; import isPresentationRole from '../util/isPresentationRole'; +const { hasOwn } = Object; + const errorMessage = 'Interactive elements should not be assigned non-interactive roles.'; export default ({ diff --git a/src/rules/no-noninteractive-element-interactions.js b/src/rules/no-noninteractive-element-interactions.js index 5ef5d5cc7..fc0ed96d8 100644 --- a/src/rules/no-noninteractive-element-interactions.js +++ b/src/rules/no-noninteractive-element-interactions.js @@ -16,7 +16,6 @@ import { propName, } from 'jsx-ast-utils'; import type { JSXOpeningElement } from 'ast-types-flow'; -import hasOwn from 'hasown'; import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; import { arraySchema, generateObjSchema } from '../util/schemas'; import getElementType from '../util/getElementType'; @@ -29,6 +28,8 @@ import isNonInteractiveElement from '../util/isNonInteractiveElement'; import isNonInteractiveRole from '../util/isNonInteractiveRole'; import isPresentationRole from '../util/isPresentationRole'; +const { hasOwn } = Object; + const errorMessage = 'Non-interactive elements should not be assigned mouse or keyboard event listeners.'; const defaultInteractiveProps = [].concat( diff --git a/src/rules/no-noninteractive-element-to-interactive-role.js b/src/rules/no-noninteractive-element-to-interactive-role.js index 6a17254da..f3612f5fa 100644 --- a/src/rules/no-noninteractive-element-to-interactive-role.js +++ b/src/rules/no-noninteractive-element-to-interactive-role.js @@ -14,7 +14,6 @@ import { propName, } from 'jsx-ast-utils'; import type { JSXIdentifier } from 'ast-types-flow'; -import hasOwn from 'hasown'; import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; import type { ESLintJSXAttribute } from '../../flow/eslint-jsx'; import getElementType from '../util/getElementType'; @@ -22,6 +21,8 @@ import getExplicitRole from '../util/getExplicitRole'; import isNonInteractiveElement from '../util/isNonInteractiveElement'; import isInteractiveRole from '../util/isInteractiveRole'; +const { hasOwn } = Object; + const errorMessage = 'Non-interactive elements should not be assigned interactive roles.'; export default ({ diff --git a/src/rules/no-redundant-roles.js b/src/rules/no-redundant-roles.js index 9fce8d784..ff7e8c3ae 100644 --- a/src/rules/no-redundant-roles.js +++ b/src/rules/no-redundant-roles.js @@ -9,13 +9,14 @@ // Rule Definition // ---------------------------------------------------------------------------- -import hasOwn from 'hasown'; import type { JSXOpeningElement } from 'ast-types-flow'; import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; import getElementType from '../util/getElementType'; import getExplicitRole from '../util/getExplicitRole'; import getImplicitRole from '../util/getImplicitRole'; +const { hasOwn } = Object; + const errorMessage = (element, implicitRole) => ( `The element ${element} has an implicit role of ${implicitRole}. Defining this explicitly is redundant and should be avoided.` ); diff --git a/src/util/getElementType.js b/src/util/getElementType.js index 6fde9fe81..2c0e815b8 100644 --- a/src/util/getElementType.js +++ b/src/util/getElementType.js @@ -3,11 +3,12 @@ */ import type { JSXOpeningElement } from 'ast-types-flow'; -import hasOwn from 'hasown'; import { elementType, getProp, getLiteralPropValue } from 'jsx-ast-utils'; import type { ESLintContext } from '../../flow/eslint'; +const { hasOwn } = Object; + const getElementType = (context: ESLintContext): ((node: JSXOpeningElement) => string) => { const { settings } = context; const polymorphicPropName = settings['jsx-a11y']?.polymorphicPropName; From 0298c547e4335440190262bdcde77238e49aa4d3 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Fri, 25 Oct 2024 16:03:12 +0300 Subject: [PATCH 3/4] [Refactor] avoid spreading things that are already arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: v1rtl Co-authored-by: Michaƫl De Boey --- __mocks__/genInteractives.js | 4 ++-- __tests__/src/rules/aria-props-test.js | 2 +- __tests__/src/rules/aria-role-test.js | 2 +- __tests__/src/rules/aria-unsupported-elements-test.js | 2 +- src/rules/role-has-required-aria-props.js | 4 +++- src/util/isInteractiveElement.js | 2 +- src/util/isInteractiveRole.js | 2 +- src/util/isNonInteractiveElement.js | 4 ++-- src/util/isNonInteractiveRole.js | 2 +- 9 files changed, 13 insertions(+), 11 deletions(-) diff --git a/__mocks__/genInteractives.js b/__mocks__/genInteractives.js index e6e4a3767..1325954e8 100644 --- a/__mocks__/genInteractives.js +++ b/__mocks__/genInteractives.js @@ -12,8 +12,8 @@ import type { JSXElementMockType } from './JSXElementMock'; const { fromEntries } = Object; -const domElements = [...dom.keys()]; -const roleNames = [...roles.keys()]; +const domElements = dom.keys(); +const roleNames = roles.keys(); const interactiveElementsMap = { a: [{ prop: 'href', value: '#' }], diff --git a/__tests__/src/rules/aria-props-test.js b/__tests__/src/rules/aria-props-test.js index 71c26d363..db5e1709b 100644 --- a/__tests__/src/rules/aria-props-test.js +++ b/__tests__/src/rules/aria-props-test.js @@ -19,7 +19,7 @@ import getSuggestion from '../../../src/util/getSuggestion'; // ----------------------------------------------------------------------------- const ruleTester = new RuleTester(); -const ariaAttributes = [...aria.keys()]; +const ariaAttributes = aria.keys(); const errorMessage = (name) => { const suggestions = getSuggestion(name, ariaAttributes); diff --git a/__tests__/src/rules/aria-role-test.js b/__tests__/src/rules/aria-role-test.js index 21a51fe07..b43c8dd8f 100644 --- a/__tests__/src/rules/aria-role-test.js +++ b/__tests__/src/rules/aria-role-test.js @@ -24,7 +24,7 @@ const errorMessage = { type: 'JSXAttribute', }; -const roleKeys = [...roles.keys()]; +const roleKeys = roles.keys(); const validRoles = roleKeys.filter((role) => roles.get(role).abstract === false); const invalidRoles = roleKeys.filter((role) => roles.get(role).abstract === true); diff --git a/__tests__/src/rules/aria-unsupported-elements-test.js b/__tests__/src/rules/aria-unsupported-elements-test.js index 4ec6e4caf..b762386d5 100644 --- a/__tests__/src/rules/aria-unsupported-elements-test.js +++ b/__tests__/src/rules/aria-unsupported-elements-test.js @@ -26,7 +26,7 @@ const errorMessage = (invalidProp) => ({ type: 'JSXOpeningElement', }); -const domElements = [...dom.keys()]; +const domElements = dom.keys(); // Generate valid test cases const roleValidityTests = domElements.map((element) => { const isReserved = dom.get(element).reserved || false; diff --git a/src/rules/role-has-required-aria-props.js b/src/rules/role-has-required-aria-props.js index a39d066a2..46f6f0c16 100644 --- a/src/rules/role-has-required-aria-props.js +++ b/src/rules/role-has-required-aria-props.js @@ -20,6 +20,8 @@ import isSemanticRoleElement from '../util/isSemanticRoleElement'; const schema = generateObjSchema(); +const roleKeys = roles.keys(); + export default { meta: { docs: { @@ -59,7 +61,7 @@ export default { const normalizedValues = String(roleAttrValue).toLowerCase().split(' '); const validRoles = normalizedValues - .filter((val) => [...roles.keys()].indexOf(val) > -1); + .filter((val) => roleKeys.indexOf(val) > -1); // Check semantic DOM elements // For example, diff --git a/src/util/isInteractiveElement.js b/src/util/isInteractiveElement.js index 9a2328ccf..e95a1befc 100644 --- a/src/util/isInteractiveElement.js +++ b/src/util/isInteractiveElement.js @@ -14,7 +14,7 @@ import { import attributesComparator from './attributesComparator'; -const roleKeys = [...roles.keys()]; +const roleKeys = roles.keys(); const elementRoleEntries = [...elementRoles]; const nonInteractiveRoles = new Set(roleKeys diff --git a/src/util/isInteractiveRole.js b/src/util/isInteractiveRole.js index a55bbf66f..f57a12d26 100644 --- a/src/util/isInteractiveRole.js +++ b/src/util/isInteractiveRole.js @@ -3,7 +3,7 @@ import { roles as rolesMap } from 'aria-query'; import type { Node } from 'ast-types-flow'; import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; -const roles = [...rolesMap.keys()]; +const roles = rolesMap.keys(); const interactiveRoles = roles.filter((name) => ( !rolesMap.get(name).abstract && rolesMap.get(name).superClass.some((klasses) => klasses.includes('widget')) diff --git a/src/util/isNonInteractiveElement.js b/src/util/isNonInteractiveElement.js index 3cd17c3a1..546d2319d 100644 --- a/src/util/isNonInteractiveElement.js +++ b/src/util/isNonInteractiveElement.js @@ -15,7 +15,7 @@ import type { Node } from 'ast-types-flow'; import attributesComparator from './attributesComparator'; -const roleKeys = [...roles.keys()]; +const roleKeys = roles.keys(); const elementRoleEntries = [...elementRoles]; const nonInteractiveRoles = new Set(roleKeys @@ -62,7 +62,7 @@ const nonInteractiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSch const nonInteractiveAXObjects = new Set(AXObjects.keys().filter((name) => ['window', 'structure'].includes(AXObjects.get(name).type))); -const nonInteractiveElementAXObjectSchemas = [...elementAXObjects].flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [])); +const nonInteractiveElementAXObjectSchemas = elementAXObjects.flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [])); function checkIsNonInteractiveElement(tagName, attributes): boolean { function elementSchemaMatcher(elementSchema) { diff --git a/src/util/isNonInteractiveRole.js b/src/util/isNonInteractiveRole.js index a4992116f..526ab1e49 100644 --- a/src/util/isNonInteractiveRole.js +++ b/src/util/isNonInteractiveRole.js @@ -9,7 +9,7 @@ import { import type { Node } from 'ast-types-flow'; import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; -const nonInteractiveRoles = [...rolesMap.keys()].filter((name) => ( +const nonInteractiveRoles = rolesMap.keys().filter((name) => ( !rolesMap.get(name).abstract && !rolesMap.get(name).superClass.some((klasses) => klasses.includes('widget')) )); From 9ff0f5f77e6f87f87fe5492d4e68b77bdc1f4b21 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Fri, 25 Oct 2024 16:20:05 +0300 Subject: [PATCH 4/4] [flow] update flow so there are no errors --- __mocks__/genInteractives.js | 2 +- __tests__/__util__/ruleOptionsMapperFactory.js | 2 +- flow/eslint.js | 1 + package.json | 2 +- src/rules/anchor-ambiguous-text.js | 3 +-- src/rules/anchor-is-valid.js | 2 +- src/rules/control-has-associated-label.js | 6 +++++- src/rules/label-has-associated-control.js | 2 +- src/rules/media-has-caption.js | 4 ++-- src/rules/mouse-events-have-key-events.js | 2 +- src/rules/no-redundant-roles.js | 4 ++-- src/util/getExplicitRole.js | 2 +- src/util/isInteractiveElement.js | 4 ++-- src/util/isNonInteractiveElement.js | 6 +++--- 14 files changed, 23 insertions(+), 19 deletions(-) diff --git a/__mocks__/genInteractives.js b/__mocks__/genInteractives.js index 1325954e8..5e41858d5 100644 --- a/__mocks__/genInteractives.js +++ b/__mocks__/genInteractives.js @@ -170,7 +170,7 @@ export function genInteractiveElements(): Array { if (bracketIndex > -1) { name = elementSymbol.slice(0, bracketIndex); } - const attributes = interactiveElementsMap[elementSymbol].map(({ prop, value }) => JSXAttributeMock(prop, value)); + const attributes = interactiveElementsMap[(elementSymbol: any)].map(({ prop, value }) => JSXAttributeMock(prop, value)); return JSXElementMock(name, attributes); }); } diff --git a/__tests__/__util__/ruleOptionsMapperFactory.js b/__tests__/__util__/ruleOptionsMapperFactory.js index 9b77f951b..71fefb733 100644 --- a/__tests__/__util__/ruleOptionsMapperFactory.js +++ b/__tests__/__util__/ruleOptionsMapperFactory.js @@ -23,7 +23,7 @@ export default function ruleOptionsMapperFactory(ruleOptions: Array = []) code, errors, // Flatten the array of objects in an array of one object. - options: [fromEntries((options || []).concat(ruleOptions).flatMap((item) => entries(item)))], + options: [fromEntries((options || []).concat(ruleOptions).flatMap((item) => entries((item: any))))], parserOptions, settings, }; diff --git a/flow/eslint.js b/flow/eslint.js index af299b6b3..49622e6a5 100644 --- a/flow/eslint.js +++ b/flow/eslint.js @@ -4,6 +4,7 @@ export type ESLintReport = { node: any, message: string, + data?: any }; export type ESLintSettings = { diff --git a/package.json b/package.json index e69ce7da7..6f2d3cd96 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "eslint-plugin-flowtype": "^5.8.0 || ^8.0.3", "eslint-plugin-import": "^2.31.0", "estraverse": "^5.3.0", - "flow-bin": "^0.147.0", + "flow-bin": "^0.250.0", "in-publish": "^2.0.1", "jackspeak": "=2.1.1", "jscodeshift": "^17.0.0", diff --git a/src/rules/anchor-ambiguous-text.js b/src/rules/anchor-ambiguous-text.js index 74258f9ec..2998bfe25 100644 --- a/src/rules/anchor-ambiguous-text.js +++ b/src/rules/anchor-ambiguous-text.js @@ -7,7 +7,6 @@ // ---------------------------------------------------------------------------- // Rule Definition // ---------------------------------------------------------------------------- - import type { ESLintConfig, ESLintContext } from '../../flow/eslint'; import { arraySchema, generateObjSchema } from '../util/schemas'; import getAccessibleChildText from '../util/getAccessibleChildText'; @@ -44,7 +43,7 @@ export default ({ const ambiguousWords = new Set(words); return { - JSXOpeningElement: (node) => { + JSXOpeningElement: (node: any) => { const nodeType = elementType(node); // Only check anchor elements and custom types. diff --git a/src/rules/anchor-is-valid.js b/src/rules/anchor-is-valid.js index 2d518c355..cf042b0d6 100644 --- a/src/rules/anchor-is-valid.js +++ b/src/rules/anchor-is-valid.js @@ -60,7 +60,7 @@ export default ({ // Create active aspect flag object. Failing checks will only report // if the related flag is set to true. - const activeAspects = {}; + const activeAspects: Object = {}; allAspects.forEach((aspect) => { activeAspects[aspect] = aspects.indexOf(aspect) !== -1; }); diff --git a/src/rules/control-has-associated-label.js b/src/rules/control-has-associated-label.js index d8feea6a1..2750d6e54 100644 --- a/src/rules/control-has-associated-label.js +++ b/src/rules/control-has-associated-label.js @@ -12,7 +12,11 @@ import { getProp, getLiteralPropValue } from 'jsx-ast-utils'; import type { JSXElement } from 'ast-types-flow'; import { generateObjSchema, arraySchema } from '../util/schemas'; -import type { ESLintConfig, ESLintContext, ESLintVisitorSelectorConfig } from '../../flow/eslint'; +import type { + ESLintConfig, + ESLintContext, + ESLintVisitorSelectorConfig, +} from '../../flow/eslint'; import getElementType from '../util/getElementType'; import isDOMElement from '../util/isDOMElement'; import isHiddenFromScreenReader from '../util/isHiddenFromScreenReader'; diff --git a/src/rules/label-has-associated-control.js b/src/rules/label-has-associated-control.js index 8920e64ed..23c6668b8 100644 --- a/src/rules/label-has-associated-control.js +++ b/src/rules/label-has-associated-control.js @@ -36,7 +36,7 @@ const schema = generateObjSchema({ }, }); -function validateID(node, context) { +function validateID(node: Object, context: Object) { const { settings } = context; const htmlForAttributes = settings['jsx-a11y']?.attributes?.for ?? ['htmlFor']; diff --git a/src/rules/media-has-caption.js b/src/rules/media-has-caption.js index 8e46fae31..2be387598 100644 --- a/src/rules/media-has-caption.js +++ b/src/rules/media-has-caption.js @@ -25,14 +25,14 @@ const schema = generateObjSchema({ track: arraySchema, }); -const isMediaType = (context, type) => { +const isMediaType = (context: Object, type: string) => { const options = context.options[0] || {}; return MEDIA_TYPES .concat(MEDIA_TYPES.flatMap((mediaType) => options[mediaType])) .some((typeToCheck) => typeToCheck === type); }; -const isTrackType = (context, type) => { +const isTrackType = (context: Object, type: string) => { const options = context.options[0] || {}; return ['track'].concat(options.track || []).some((typeToCheck) => typeToCheck === type); }; diff --git a/src/rules/mouse-events-have-key-events.js b/src/rules/mouse-events-have-key-events.js index 386c99870..2c38514ae 100644 --- a/src/rules/mouse-events-have-key-events.js +++ b/src/rules/mouse-events-have-key-events.js @@ -40,7 +40,7 @@ export default ({ }, create: (context: ESLintContext) => ({ - JSXOpeningElement: (node) => { + JSXOpeningElement: (node: Object) => { const { name } = node.name; if (!dom.get(name)) { diff --git a/src/rules/no-redundant-roles.js b/src/rules/no-redundant-roles.js index ff7e8c3ae..6501512d3 100644 --- a/src/rules/no-redundant-roles.js +++ b/src/rules/no-redundant-roles.js @@ -17,7 +17,7 @@ import getImplicitRole from '../util/getImplicitRole'; const { hasOwn } = Object; -const errorMessage = (element, implicitRole) => ( +const errorMessage = (element: string, implicitRole: string) => ( `The element ${element} has an implicit role of ${implicitRole}. Defining this explicitly is redundant and should be avoided.` ); @@ -46,7 +46,7 @@ export default ({ const elementType = getElementType(context); return { JSXOpeningElement: (node: JSXOpeningElement) => { - const type = elementType(node); + const type: any = elementType(node); const implicitRole = getImplicitRole(type, node.attributes); const explicitRole = getExplicitRole(type, node.attributes); diff --git a/src/util/getExplicitRole.js b/src/util/getExplicitRole.js index 185c1f50a..16992b74c 100644 --- a/src/util/getExplicitRole.js +++ b/src/util/getExplicitRole.js @@ -15,7 +15,7 @@ export default function getExplicitRole( tag: string, attributes: Array, ): ?string { - const explicitRole = (function toLowerCase(role) { + const explicitRole = (function toLowerCase(role: any) { if (typeof role === 'string') { return role.toLowerCase(); } diff --git a/src/util/isInteractiveElement.js b/src/util/isInteractiveElement.js index e95a1befc..39364a6f9 100644 --- a/src/util/isInteractiveElement.js +++ b/src/util/isInteractiveElement.js @@ -57,8 +57,8 @@ const interactiveAXObjects = new Set(AXObjects.keys().filter((name) => AXObjects const interactiveElementAXObjectSchemas = [...elementAXObjects].flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => interactiveAXObjects.has(role)) ? [elementSchema] : [])); -function checkIsInteractiveElement(tagName, attributes): boolean { - function elementSchemaMatcher(elementSchema) { +function checkIsInteractiveElement(tagName: string, attributes: Object): boolean { + function elementSchemaMatcher(elementSchema: Object) { return ( tagName === elementSchema.name && attributesComparator(elementSchema.attributes, attributes) diff --git a/src/util/isNonInteractiveElement.js b/src/util/isNonInteractiveElement.js index 546d2319d..b47153edd 100644 --- a/src/util/isNonInteractiveElement.js +++ b/src/util/isNonInteractiveElement.js @@ -62,10 +62,10 @@ const nonInteractiveElementRoleSchemas = elementRoleEntries.flatMap(([elementSch const nonInteractiveAXObjects = new Set(AXObjects.keys().filter((name) => ['window', 'structure'].includes(AXObjects.get(name).type))); -const nonInteractiveElementAXObjectSchemas = elementAXObjects.flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [])); +const nonInteractiveElementAXObjectSchemas = [...elementAXObjects].flatMap(([elementSchema, AXObjectsArr]) => (AXObjectsArr.every((role): boolean => nonInteractiveAXObjects.has(role)) ? [elementSchema] : [])); -function checkIsNonInteractiveElement(tagName, attributes): boolean { - function elementSchemaMatcher(elementSchema) { +function checkIsNonInteractiveElement(tagName: string, attributes: Object): boolean { + function elementSchemaMatcher(elementSchema: Object) { return ( tagName === elementSchema.name && tagName !== 'td' // TODO: investigate why this is needed