benjamn / recast

JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator
MIT License
4.91k stars 347 forks source link

Missing parenthesis for AwaitExpression inside an optional chain #1410

Open simonihmig opened 1 month ago

simonihmig commented 1 month ago

I was running into an issue with jscodeshift, which seems to be similar to #589. I was seeing this in astexplorer.net, which is using some older versions, but I was observing the same behaviour when running the transform with npx jscodeshift, which AFAICT should be using the latest recast version.

Here is a reproduction: https://astexplorer.net/#/gist/19cd83009b20b00367a24ded3c031eb2/d25151fcdcea6a1d24788c3606799b579eaa6f14.

When wrapping a function call (asyncFn() in this example) with an AwaitExpression, the serialized output differs when this is part of an MemberExpression vs. an OptionalMemberExpression.

// before:
asyncFn().filter(x => x);
// after:
(await asyncFn()).filter(x => x); // correct! ✅

// before:
asyncFn()?.filter(x => x);
// after:
await asyncFn()?.filter(x => x); // wrong! ❌