ESLint has released the first beta versions of v8 🎉
https://eslint.org/blog/2021/08/eslint-v8.0.0-beta.0-released
https://eslint.org/blog/2021/08/eslint-v8.0.0-beta.1-released
https://eslint.org/blog/2021/09/eslint-v8.0.0-beta.2-released
https://eslint.org/blog/2021/09/eslint-v8.0.0-rc.0-released

It would be awesome to have official ESLint 8 support. 👊
I'm happy to help where I can of course 🙂
* Note: If the node argument is an OptionalMemberExpression, it doesn't necessarily mean it is optional.
 * It just means there is an optional member somewhere inside.
 * This particular node might still represent a required member, so check .optional field.
 */
function markNode(node, optionalChains, result) {
  if (optionalChains) {
    if (node.optional) {
      
      if (!optionalChains.has(result)) {
        
        optionalChains.set(result, true);
      }
    } else {
      
      optionalChains.set(result, false);
    }
  }
}
/**
 * Assuming () means the passed node.
 * (foo) -> 'foo'
 * foo(.)bar -> 'foo.bar'
 * foo.bar(.)baz -> 'foo.bar.baz'
 * Otherwise throw.
 */
function analyzePropertyChain(node, optionalChains) {
  if (node.type === 'Identifier' || node.type === 'JSXIdentifier') {
    const result = node.name;
    if (optionalChains) {