Repository: prettier/prettier (JavaScript)

Issue:
Using compound expression with comma operator as return value of curried function
**Prettier 2.3.0**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAzArlMTAXkwAoBDAJwHMBGAGkyuoCYBKYgPjI6O4poMmNdgB0oIeiAgAHGAEt0yUFUoQA7gAUqCNMhDkANuvIBPPVIBGlcmADWcGAGUZt+VGrIYlXHClwAW0s4ABMQ0IAZcg9ccmo4ADEISgDyGAUPfXJcGAhJEAALGADDAHUC+Xg0VzA4J11K+QA3StN9MDQLEHc0OEoYTRtqVORsI16pACs0AA8AIRt7RydyALgI9zhR8b8QaZmnd2pDOABFXAh4bcMJkFdKXsp9S3Jgw3yZSncYUvkQmAKyAAHAAGKSfCC9Uo2GT6T5wR5NLZSACOF3gg1kehQ5DQAFooHBQqF8pQ4Gj5GTBnERkgxjddr0AvIvD5GUcTudLls6TspDBXr9-oCkCx+TZ5IYjgBhCABWkgBEAVnyuF6ABVXtj6bcmr4AJJQcKwJxgL5yACCRqcMFMJ2uvQAvo6gA)
<!-- prettier-ignore -->
```sh
--parser babel
```

**Input:**
<!-- prettier-ignore -->
```js
const func = (arg1, arg2) => () => (arg1, arg2)

```

**Output:**
<!-- prettier-ignore -->
```js
const func = (arg1, arg2) => () => arg1, arg2;

```

**Expected behavior:**
Using compound expression with comma operator is not usual, but is valid syntax (and can be really useful).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

It should be handled correctly by prettier in all cases, including this currying case.

Given input should result with no changes at all.
The current output is not valid JS syntax as the `arg2` variable is not declared, and this gives an error when executed.


Hints:
In the input I didn't write the ending semi-colon, and I didn't configure prettier about this, so a semi-colon was added.
This does not change anything on the issue. With or without semi-colon, the issue is the same.
I tested the same code with prettier **2.2.1**, and there was no problem with this previous version.
I wonder which PR breaks it.
Must break during function print.

Here says:

https://github.com/prettier/prettier/blob/81a1c463116f9dc8ec5e8059d70a9254675847e6/src/language-js/needs-parens.js#L351-L352
https://github.com/prettier/prettier/pull/9992 Seems the one, but I don't know how.
With updated playground (with help from its "second output" option under debug):

**Prettier 2.3.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAzArlMTAXkwAoBDAJwHMBGAGkyuoCYBKYgPjI6O4poMmNdiHogIABxgBLdMlBVKEAO4AFKgjTIQ5ADYryAT23iARpXJgA1nBgBlSVZlRqyGJVxxxcALZm4ABNAoIAZcldccmo4ADEISl9yGFlXHXJcGAgxEAALGF89AHVcmXg0JzA4ey0ymQA3MqMdMDRTEBc0OEoYNUtqJORsfS7xACs0AA8AIUsbO3tyXzhQlzghke8QCcn7F2o9OABFXAh4Db1RkCdKLsodM3IAvRzJShcYIplAmFzkAA4AAziN4QLpFSySHRvOB3errcQAR1O8D6Um0KHIaAAtFA4EEgjlKHBkTJiX1ooMkMNLlsur4ZO5PHT9ocTmd1tTNuIYE8vj8-kgWDzLDI9PsAMIQXxUkCwgCsOVwXQAKk8MTSrvUvABJKAhWD2MDvaQAQX19hgRkOFy6AF87UA)
<!-- prettier-ignore -->
```sh
--parser babel
```

**Input:**
<!-- prettier-ignore -->
```jsx
const func = (arg1, arg2) => () => (arg1, arg2)
```

**Output:**
<!-- prettier-ignore -->
```jsx
const func = (arg1, arg2) => () => arg1, arg2;

```

**Second Output:**
<!-- prettier-ignore -->
```jsx
SyntaxError: 'Const declarations' require an initialization value. (1:46)
> 1 | const func = (arg1, arg2) => () => arg1, arg2;
    |                                              ^
  2 |
```

---

with TypeScript:

**Prettier 2.3.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAzArlMTAXkwAoBDAJwHMBGAGkyuoCYBKYgPjI6O4poMmNdiHogIABxgBLdMlBVKEAO4AFKgjTIQ5ADYryAT23iARpXJgA1nBgBlSVZlRqyGJVxxxcALZm4ABNAoIAZcldccmo4ADEISl9yGFlXHXJcGAgxEAALGF89AHVcmXg0JzA4ey0ymQA3MqMdMDRTEBc0OEoYNUtqJORsfS7xACs0AA8AIUsbO3tyXzhQlzghke8QCcn7F2o9OABFXAh4Db1RkCdKLsodGCNJODQwShlpHMl32CKZQJguWQAA4AAzib4QLpFSySHTfF7derrcQAR1O8D6Um0KHIaAAtFA4EEgjlKHB0TJyX1ooMkMNLlsur4ZO5PEz9ocTmd1vTNuIYOQzH8AUCkCwBZYZHp9gBhCC+OkgF4AVhyuC6ABUhTiGVd6l4AJJQEKwexvD4wACCJvsj0OFy6AF8nUA)
<!-- prettier-ignore -->
```sh
--parser typescript
```

**Input:**
<!-- prettier-ignore -->
```tsx
const func = (arg1, arg2) => () => (arg1, arg2)
```

**Output:**
<!-- prettier-ignore -->
```tsx
const func = (arg1, arg2) => () => arg1, arg2;

```

**Second Output:**
<!-- prettier-ignore -->
```tsx
const func = (arg1, arg2) => () => arg1,
  arg2;

```

---

With Flow, the second output would be an error as well.

Patch:
diff --git a/src/language-js/print/function.js b/src/language-js/print/function.js
--- a/src/language-js/print/function.js
+++ b/src/language-js/print/function.js
@@ -252,13 +252,20 @@ function printArrowChain(
   const isAssignmentRhs = Boolean(args && args.assignmentLayout);
   const shouldPutBodyOnSeparateLine =
     tailNode.body.type !== "BlockStatement" &&
-    tailNode.body.type !== "ObjectExpression";
+    tailNode.body.type !== "ObjectExpression" &&
+    tailNode.body.type !== "SequenceExpression";
   const shouldBreakBeforeChain =
     (isCallee && shouldPutBodyOnSeparateLine) ||
     (args && args.assignmentLayout === "chain-tail-arrow-chain");
 
   const groupId = Symbol("arrow-chain");
 
+  // We handle sequence expressions as the body of arrows specially,
+  // so that the required parentheses end up on their own lines.
+  if (tailNode.body.type === "SequenceExpression") {
+    bodyDoc = group(["(", indent([softline, bodyDoc]), softline, ")"]);
+  }
+
   return group([
     group(
       indent([


Test patch:
diff --git a/tests/format/js/arrows/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/arrows/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/js/arrows/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/js/arrows/__snapshots__/jsfmt.spec.js.snap
@@ -3691,6 +3691,9 @@ foo(c, a => b)
 foo(c, a => b, d)
 foo(a => b, d)
 
+foo(a => (0, 1));
+foo(a => b => (0, 1));
+
 =====================================output=====================================
 promise.then(
   (result) => result,
@@ -3716,6 +3719,9 @@ foo(c, (a) => b);
 foo(c, (a) => b, d);
 foo((a) => b, d);
 
+foo((a) => (0, 1));
+foo((a) => (b) => (0, 1));
+
 ================================================================================
 `;
 
@@ -3742,6 +3748,9 @@ foo(c, a => b)
 foo(c, a => b, d)
 foo(a => b, d)
 
+foo(a => (0, 1));
+foo(a => b => (0, 1));
+
 =====================================output=====================================
 promise.then(
   result => result,
@@ -3767,5 +3776,8 @@ foo(c, a => b);
 foo(c, a => b, d);
 foo(a => b, d);
 
+foo(a => (0, 1));
+foo(a => b => (0, 1));
+
 ================================================================================
 `;
diff --git a/tests/format/js/arrows/parens.js b/tests/format/js/arrows/parens.js
--- a/tests/format/js/arrows/parens.js
+++ b/tests/format/js/arrows/parens.js
@@ -13,3 +13,6 @@ foo(a => { return b })
 foo(c, a => b)
 foo(c, a => b, d)
 foo(a => b, d)
+
+foo(a => (0, 1));
+foo(a => b => (0, 1));