`$("input:enabled:invalid")`で「unsupported pseudo: invalid」というエラーが出る（jQuery 3.3.1）


# 環境
* jQuery 3.3.1

以下のHTMLを使います。

```html
<input type="text" required value="test"> <!-- valid -->
<input type="text" required> <!-- invalid(requiedなのにvalueがない) -->
<input type="text" required disabled> 
```

<p data-height="265" data-theme-id="0" data-slug-hash="ZxJvQW" data-default-tab="js,result" data-user="yuji38kwmt" data-embed-version="2" data-pen-title="$("input:enabled:invalid ")の確認" class="codepen">See the Pen <a href="https://codepen.io/yuji38kwmt/pen/ZxJvQW/">$("input:enabled:invalid ")の確認</a> by yuji38kwmt (<a href="https://codepen.io/yuji38kwmt">@yuji38kwmt</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 問題

以下のJavaScriptをChromeで実行したところ、`$("input:enabled:invalid").length`でSyntax Errorが発生しました。

```js:Console
$("input:enabled:invalid").length; //⇒Syntax Error ("1"を期待していた)
$("input:enabled").length; //⇒2
$("input:invalid").length; //⇒1
$("input.not-exists:enabled:invalid").length; //⇒0（"input.not-exists"は存在しない要素）
```


```txt:console
Error: Syntax error, unrecognized expression: unsupported pseudo: invalid
    at Function.Sizzle.error (jquery-3.3.1.js:1541)
    at PSEUDO (jquery-3.3.1.js:1888)
    at matcherFromTokens (jquery-3.3.1.js:2437)
    at Sizzle.compile (jquery-3.3.1.js:2591)
    at Sizzle.select (jquery-3.3.1.js:2677)
    at Function.Sizzle [as find] (jquery-3.3.1.js:845)
    at jQuery.fn.init.find (jquery-3.3.1.js:2873)
    at new jQuery.fn.init (jquery-3.3.1.js:2983)
    at jQuery (jquery-3.3.1.js:139)
    at sample.html:36
```

## 他のブラウザで検証した結果

|ブラウザ|結果|
|:--:|:--|
|Google Chrome 65.0.3325.181|NG|
|Internet Explorer 11.309.16299.0|NG|
|Microsoft Edge 41.16299.248.0|OK|
|Firefox 59.0.1|OK|


# エラーの調査

```js:jquery-3.3.1.js_(1881行-1916行)
		"PSEUDO": function( pseudo, argument ) {
			// pseudo-class names are case-insensitive
			// http://www.w3.org/TR/selectors/#pseudo-classes
			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
			// Remember that setFilters inherits from pseudos
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );

			// The user may use createPseudo to indicate that
			// arguments are needed to create the filter function
			// just as Sizzle does
			if ( fn[ expando ] ) {
				return fn( argument );
			}

			// But maintain support for old signatures
			if ( fn.length > 1 ) {
				args = [ pseudo, pseudo, "", argument ];
				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
					markFunction(function( seed, matches ) {
						var idx,
							matched = fn( seed, argument ),
							i = matched.length;
						while ( i-- ) {
							idx = indexOf( seed, matched[i] );
							seed[ idx ] = !( matches[ idx ] = matched[i] );
						}
					}) :
					function( elem ) {
						return fn( elem, 0, args );
					};
			}

			return fn;
		}
```        

`at PSEUDO (jquery-3.3.1.js:1888)`は、以下の処理です。

```js:jquery-3.3.1.js_(1886行-1888行)
			var args,
				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
					Sizzle.error( "unsupported pseudo: " + pseudo );
```

`Expr.pseudos[ pseudo ]` , `Expr.setFilters[ pseudo.toLowerCase() ] `がundefined or nullのため、`Sizzle.error`が呼ばれたようです。

以下の場合、1888行目の処理を通りませんでした。

* Firefoxで、`$("input:enabled:invalid").length`を実行したとき
* Chromeで、`$("input:invalid").length`を実行したとき


これ以上のことは分かりませんでした。


# 【補足】`document.querySelectorAll`の場合

Chromeでエラーは発生しませんでした。

```js:Console
document.querySelectorAll("input:enabled").length; //⇒2
document.querySelectorAll("input:invalid").length; //⇒1
document.querySelectorAll("input:enabled:invalid").length; //⇒1
```

# 【補足】 CSSの場合

期待通りの結果でした（CodePen参照）。

```css
input:enabled {
  border-left-color: red;
}

input:invalid {
  border-right-color: red;
}

input:enabled:invalid {
  border-top-color: red;
}
```



# そもそもやりたかったこと

Enabled/Disabledが切り替わるテキストボックスに対して、入力チェックをしたいです。
そのため、`$("input:enabled:invalid")`と記述しました。
しかし`$("input:invalid")`でDisabledのテキストボックスが除外されたので、`$("input:invalid")`で私のやりたいことは実現できました。

# 感想
GitHubにIssueを出して、回答をいただきました。
https://github.com/jquery/jquery/issues/4021

>Thank you for opening an issue! However, the :invalid selector is not officially supported in jQuery. It works natively, but Sizzle doesn't trust native qSA with :enabled/:disabled due to a certain qSA bug in Chrome. There are a couple workarounds.

そもそもjQueryは`:invalid`をサポートしていませんでした。
確かに公式サイトに`:invalid`は掲載されていませんね。
https://api.jquery.com/category/selectors/

* `qSA`は`document.querySelectorAll`のことだと思います。

https://github.com/jquery/jquery/issues/3350

`$("input").filter(":invalid")`でも同様のエラーが発生します。