Repository: babel/babel
File: packages/babel-generator/src/node/parentheses.ts (TypeScript)

Code before:
        computed: true,
      }) ||
      isOptionalMemberExpression(parent, {
        object: node,
        computed: true,
        optional: false,
      });
    return isFirstInContext(
      printStack,
      isFollowedByBracket
        ? CheckParam.expressionStatement |
            CheckParam.forHead |
            CheckParam.forInHead |
            CheckParam.forOfHead
        : CheckParam.forOfHead,
    );
  }

  // ECMAScript specifically forbids a for-of loop from starting with the
  // token sequence `for (async of`, because it would be ambiguous with
  // `for (async of => {};;)`, so we need to add extra parentheses.
  return (
    node.name === "async" &&
    isForOfStatement(parent) &&
    node === parent.left &&
    !parent.await
  );
}

// Walk up the print stack to determine if our node can come first
// in a particular context.
function isFirstInContext(
  printStack: Array<t.Node>,
  checkParam: CheckParam,
): boolean {
  const expressionStatement = checkParam & CheckParam.expressionStatement;
  const arrowBody = checkParam & CheckParam.arrowBody;
  const exportDefault = checkParam & CheckParam.exportDefault;
  const forHead = checkParam & CheckParam.forHead;
  const forInHead = checkParam & CheckParam.forInHead;
  const forOfHead = checkParam & CheckParam.forOfHead;

  let i = printStack.length - 1;
  if (i <= 0) return;
  let node = printStack[i];
  i--;
  let parent = printStack[i];
  while (i >= 0) {
    const parentType = parent.type;
    if (
      (expressionStatement &&

Review comment (suggestion):
```suggestion
    isForOfStatement(parent, { left: node, await: false })
```
If for-await was introduced before Babel 7 so that every parser ^7.0.0 consistently set `await` to `false`.

Code after:
        computed: true,
      }) ||
      isOptionalMemberExpression(parent, {
        object: node,
        computed: true,
        optional: false,
      });
    return isFirstInContext(
      printStack,
      isFollowedByBracket
        ? CheckParam.expressionStatement |
            CheckParam.forHead |
            CheckParam.forInHead |
            CheckParam.forOfHead
        : CheckParam.forOfHead,
    );
  }

  // ECMAScript specifically forbids a for-of loop from starting with the
  // token sequence `for (async of`, because it would be ambiguous with
  // `for (async of => {};;)`, so we need to add extra parentheses.
  return (
    node.name === "async" &&
    isForOfStatement(parent, { left: node, await: false })
  );
}

// Walk up the print stack to determine if our node can come first
// in a particular context.
function isFirstInContext(
  printStack: Array<t.Node>,
  checkParam: CheckParam,
): boolean {
  const expressionStatement = checkParam & CheckParam.expressionStatement;
  const arrowBody = checkParam & CheckParam.arrowBody;
  const exportDefault = checkParam & CheckParam.exportDefault;
  const forHead = checkParam & CheckParam.forHead;
  const forInHead = checkParam & CheckParam.forInHead;
  const forOfHead = checkParam & CheckParam.forOfHead;

  let i = printStack.length - 1;
  if (i <= 0) return;
  let node = printStack[i];
  i--;
  let parent = printStack[i];
  while (i >= 0) {
    const parentType = parent.type;
    if (
      (expressionStatement &&
        parentType === "ExpressionStatement" &&
        parent.expression === node) ||