Skip to content

[Bug]: Generator prints the identifier let in some forbidden places #13268

@Zalathar

Description

@Zalathar

💻

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (babel.transform, babel.parse)

Input code

Non-strict code allows let as an identifier. To avoid ambiguity, the grammar prohibits let as an identifier token in places where it would be confused with the let contextual keyword. The generator is not aware of these restrictions, so it emits illegal or incorrect code for a valid AST.

for ((let)[x];;);

for ((let)[x] in {});

(let)[x];

for ((let) of []);

async () => {
  for await ((let) of []);
};

Babel REPL link

Configuration file name

No response

Configuration

{}

Current and expected behavior

Expected behaviour: The input is emitted as-is, with extra parentheses to ensure that let is treated as an identifier.

Actual behaviour: The generated code is illegal or incorrect:

for (let[x];;);

for (let[x] in {});

let[x];

for (let of []);

async () => {
  for await (let of []);
};

Environment

  • Babel v7.14.1

Possible solution

Generator's parentheses.ts already has a helper function isFirstInStatement that does the hard work of figuring out whether an AST node could emit the first token in a particular context. It just needs some extra flags to treat for-loop heads as a successful match, and optionally not treat ExpressionStatement as a match (if the identifier is not followed by [).

Some contexts only prohibit let [. We can detect this case by checking t.isMemberExpression(parent, { object: node, computed: true }).

With these components, we can add a case to Identifier that requests parentheses when let would occur in an illegal context.

Additional context

No response

Metadata

Metadata

Assignees

Labels

outdatedA closed issue/PR that is archived due to age. Recommended to make a new issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions