diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f451e3fb3..cfddf0d60f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,14 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
## Unreleased
+### Fixed
+* [`no-unknown-property`]: add properties `onToggle`, `fill`, `as`, and pointer events ([#3385][] @sjarva)
+* [`no-unknown-property`]: add `defaultChecked` property ([#3385][] @sjarva)
+* [`no-unknown-property`]: add touch and media event related properties ([#3385][] @sjarva)
+* [`no-unknown-property`]: `children` is always an acceptable prop; iframes have `scrolling`; ; video has `playsInline` ([#3385][] @ljharb)
+
+[#3385]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3385
+
## [7.31.4] - 2022.09.04
### Fixed
diff --git a/lib/rules/no-unknown-property.js b/lib/rules/no-unknown-property.js
index 2f883af8fb..a7bd0291ec 100644
--- a/lib/rules/no-unknown-property.js
+++ b/lib/rules/no-unknown-property.js
@@ -30,9 +30,57 @@ const ATTRIBUTE_TAGS_MAP = {
checked: ['input'],
// image is required for SVG support, all other tags are HTML.
crossOrigin: ['script', 'img', 'video', 'audio', 'link', 'image'],
- fill: ['svg'],
+ fill: [ // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill
+ // Fill color
+ 'altGlyph',
+ 'circle',
+ 'ellipse',
+ 'g',
+ 'path',
+ 'polygon',
+ 'polyline',
+ 'rect',
+ 'svg',
+ 'text',
+ 'textPath',
+ 'tref',
+ 'tspan',
+ // Animation final state
+ 'animate',
+ 'animateColor',
+ 'animateMotion',
+ 'animateTransform',
+ 'set',
+ ],
property: ['meta'],
viewBox: ['svg'],
+ as: ['link'],
+ // Media events allowed only on audio and video tags, see https://github.com/facebook/react/blob/256aefbea1449869620fb26f6ec695536ab453f5/CHANGELOG.md#notable-enhancements
+ onAbort: ['audio', 'video'],
+ onCanPlay: ['audio', 'video'],
+ onCanPlayThrough: ['audio', 'video'],
+ onDurationChange: ['audio', 'video'],
+ onEmptied: ['audio', 'video'],
+ onEncrypted: ['audio', 'video'],
+ onEnded: ['audio', 'video'],
+ onError: ['audio', 'video'],
+ onLoadedData: ['audio', 'video'],
+ onLoadedMetadata: ['audio', 'video'],
+ onLoadStart: ['audio', 'video'],
+ onPause: ['audio', 'video'],
+ onPlay: ['audio', 'video'],
+ onPlaying: ['audio', 'video'],
+ onProgress: ['audio', 'video'],
+ onRateChange: ['audio', 'video'],
+ onSeeked: ['audio', 'video'],
+ onSeeking: ['audio', 'video'],
+ onStalled: ['audio', 'video'],
+ onSuspend: ['audio', 'video'],
+ onTimeUpdate: ['audio', 'video'],
+ onVolumeChange: ['audio', 'video'],
+ onWaiting: ['audio', 'video'],
+ scrolling: ['iframe'],
+ playsInline: ['video'],
};
const SVGDOM_ATTRIBUTE_NAMES = {
@@ -127,7 +175,7 @@ const DOM_PROPERTY_NAMES_ONE_WORD = [
// Element specific attributes
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes (includes global attributes too)
// To be considered if these should be added also to ATTRIBUTE_TAGS_MAP
- 'accept', 'action', 'allow', 'alt', 'async', 'buffered', 'capture', 'challenge', 'cite', 'code', 'cols',
+ 'accept', 'action', 'allow', 'alt', 'as', 'async', 'buffered', 'capture', 'challenge', 'cite', 'code', 'cols',
'content', 'coords', 'csp', 'data', 'decoding', 'default', 'defer', 'disabled', 'form',
'headers', 'height', 'high', 'href', 'icon', 'importance', 'integrity', 'kind', 'label',
'language', 'loading', 'list', 'loop', 'low', 'max', 'media', 'method', 'min', 'multiple', 'muted',
@@ -149,7 +197,7 @@ const DOM_PROPERTY_NAMES_ONE_WORD = [
// OpenGraph meta tag attributes
'property',
// React specific attributes
- 'ref', 'key',
+ 'ref', 'key', 'children',
];
const DOM_PROPERTY_NAMES_TWO_WORDS = [
@@ -168,7 +216,7 @@ const DOM_PROPERTY_NAMES_TWO_WORDS = [
'onCompositionUpdate', 'onCut', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',
'onError', 'onFocus', 'onInput', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onLoad', 'onWheel', 'onDragOver',
'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver',
- 'onMouseUp', 'onPaste', 'onScroll', 'onSelect', 'onSubmit', 'onTransitionEnd', 'radioGroup', 'readOnly', 'referrerPolicy',
+ 'onMouseUp', 'onPaste', 'onScroll', 'onSelect', 'onSubmit', 'onToggle', 'onTransitionEnd', 'radioGroup', 'readOnly', 'referrerPolicy',
'rowSpan', 'srcDoc', 'srcLang', 'srcSet', 'useMap',
// SVG attributes
// See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
@@ -204,7 +252,11 @@ const DOM_PROPERTY_NAMES_TWO_WORDS = [
'autoCorrect', // https://stackoverflow.com/questions/47985384/html-autocorrect-for-text-input-is-not-working
'autoSave', // https://stackoverflow.com/questions/25456396/what-is-autosave-attribute-supposed-to-do-how-do-i-use-it
// React specific attributes https://reactjs.org/docs/dom-elements.html#differences-in-attributes
- 'className', 'dangerouslySetInnerHTML', 'defaultValue', 'htmlFor', 'onChange', 'suppressContentEditableWarning', 'suppressHydrationWarning',
+ 'className', 'dangerouslySetInnerHTML', 'defaultValue', 'defaultChecked', 'htmlFor', 'onChange',
+ 'onInvalid', 'onReset', 'onTouchCancel', 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'suppressContentEditableWarning', 'suppressHydrationWarning',
+ 'onAbort', 'onCanPlay', 'onCanPlayThrough', 'onDurationChange', 'onEmptied', 'onEncrypted', 'onEnded',
+ 'onLoadedData', 'onLoadedMetadata', 'onLoadStart', 'onPause', 'onPlay', 'onPlaying', 'onProgress', 'onRateChange',
+ 'onSeeked', 'onSeeking', 'onStalled', 'onSuspend', 'onTimeUpdate', 'onVolumeChange', 'onWaiting',
];
const DOM_PROPERTIES_IGNORE_CASE = ['charset'];
@@ -226,11 +278,28 @@ const ARIA_PROPERTIES = [
'aria-posinset', 'aria-rowcount', 'aria-rowindex', 'aria-rowindextext', 'aria-rowspan', 'aria-setsize',
];
+const REACT_ON_PROPS = [
+ 'onGotPointerCapture',
+ 'onLostPointerCapture',
+ 'onPointerCancel',
+ 'onPointerDown',
+ 'onPointerEnter',
+ 'onPointerLeave',
+ 'onPointerMove',
+ 'onPointerOut',
+ 'onPointerOver',
+ 'onPointerUp',
+];
+
function getDOMPropertyNames(context) {
const ALL_DOM_PROPERTY_NAMES = DOM_PROPERTY_NAMES_TWO_WORDS.concat(DOM_PROPERTY_NAMES_ONE_WORD);
// this was removed in React v16.1+, see https://github.com/facebook/react/pull/10823
if (!testReactVersion(context, '>= 16.1.0')) {
- return ['allowTransparency'].concat(ALL_DOM_PROPERTY_NAMES);
+ return ALL_DOM_PROPERTY_NAMES.concat('allowTransparency');
+ }
+ // these were added in React v16.4.0, see https://reactjs.org/blog/2018/05/23/react-v-16-4.html and https://github.com/facebook/react/pull/12507
+ if (testReactVersion(context, '>= 16.4.0')) {
+ return ALL_DOM_PROPERTY_NAMES.concat(REACT_ON_PROPS);
}
return ALL_DOM_PROPERTY_NAMES;
}
diff --git a/tests/lib/rules/no-unknown-property.js b/tests/lib/rules/no-unknown-property.js
index 7883afd23c..d03179ef75 100644
--- a/tests/lib/rules/no-unknown-property.js
+++ b/tests/lib/rules/no-unknown-property.js
@@ -48,11 +48,25 @@ ruleTester.run('no-unknown-property', rule, {
{ code: '' },
{ code: '' },
{ code: '' },
+ { code: '