Repository: alangpierce/sucrase (ts)

Issue:
Failing transform of the d3 module
Hello,

I found a bug in the transform of the next ES code https://sucrase.io/#compareWithTypeScript=true&compressedCode=H4sIAHD13mAAA2WNzQqDMBAG7z7FdzREiofSQyUtXvoewSQgaFLWbLDUvnvjz6k97S7DzNr5GSjCWKd5iHDsu9gHj47Hiccy6YHtVGGbwQm8C%2BSDkCEU6gq9N3Ze1yYTspHJ4zEEHS%2Fnlki%2FTo7CXwdKKXA2Xe%2BtySJwR4K6oVzDUkEmLAtqsbHrL9srZTreS3mUJ7Fboik%2BX9IsTqnaAAAA

The code is taken from `d3-array` module, https://github.com/d3/d3-array/blob/main/src/cumsum.js
Sucrase can't transpile d3-array
Over here at @toucantoco we're using Sucrase and we're quite happy with it, thanks for maintaining it! However after a deps update we can't run the tests anymore because it looks like Sucrase can't properly transpile [this file](https://github.com/d3/d3-array/blob/416f657e932690f5e023f9ced6f7cadf118b00ac/src/cumsum.js)

As you can see in [this Sucrase playground](https://sucrase.io/#selectedTransforms=typescript&compressedCode=H4sIAHoYlWEAA2WNzQqDMBAG7z7FdzREiofSQyUtXvoewSQgaFLWbLDUvnvjz6k97S7DzNr5GSjCWKd5iHDsu9gHj47Hiccy6YHtVGGbwQm8C%2BSDkCEU6gq9N3Ze1yYTspHJ4zEEHS%2Fnlki%2FTo7CXwdKKXA2Xe%2BtySJwR4K6oVzDUkEmLAtqsbHrL9srZTreS3mUJ7Fboik%2BX9IsTqnaAAAA) by checking and unchecking this `typescript` option, Sucrase fails when TS is on

However this is valid TS, and as you can see in [this TS playground](https://www.typescriptlang.org/play?ssl=6&ssc=1&pln=6&pc=2#code/KYDwDg9gTgLgBAE2AMwIYFcA29noHYDGMAlhHnAegLYDO1AFAG6qbrA0A0czrwEyASjgBvAFBxuqKHDpU4AXjgAGLsTxIQC5QG5xcKMBjoo5AGKYIqGADYALAEEoUVAE8AdMigQqTFm06SvPwK8or4SMhqwAh6EgD83AoAfHD0snAA1IoZjHAAPnnKArFwAFyJ8ilp1JnZPGz8TKrqoBkZXPXsQgVFAroAvkA), this properly transpiles to JS, and if `noImplicitAny` is set to `false` there is no error

I don't know why this happens when running our tests since [@sucrase/jest-plugin precises](https://github.com/alangpierce/sucrase/tree/main/integrations/jest-plugin) that a `.js` will not be transpiles with the typescript option

Anyway just wanted to give you a heads up on this, I have no idea how to fix it yet but I can try if you guys are too busy

Pull request:
Port babel-parser changes from 2021-07-02 to 2021-08-14
Instructions: https://github.com/alangpierce/sucrase/wiki/Porting-changes-from-Babel's-parser

9bad558d13 [babel 8] Use an identifier for `TSTypeParameter.name` (#12829)
🚫 AST-only.

bfd2f8f4b1 fix: disallow computed `async`/`get`/`set` keyword (#13531)
🚫 Validation only.

8a3e0fd960 Async do expression should start at async (#13534)
🚫 AST only.

79d3276f61 Overhaul comment attachment (#13521)
🚫 AST only.

6e57617138 Fix await binding error within static block (#13088)
🚫 Only affects validation and babel-parser scopes, which aren't in Sucrase.

2c6db56696 Allow module block to start a member expression (#13573)
🚫 Module blocks aren't supported yet, tracked in https://github.com/alangpierce/sucrase/issues/634

dd942f92af fix: parser `strictMode` option (#13548)
🚫 Option isn't relevant to Sucrase.

22b2f4fc02 Update babel-parser.d.ts (#13575)
🚫 Babel-specific types only.

e591780244 v7.14.8
🚫 Release only.

4a56387330 ts: Check if param is assignable when parsing arrow return type (#13581)
✅ Added test and implemented by re-parsing as a non-arrow-function if we get an error. Fixes #631. Fixes #666.

e4de256cdd chore: reorganize benchmarks (#13606)
🚫 Code not relevant to Sucrase.

d3a7cd5e8d Replace generic `__clone` call by specific methods (#13611)
🚫 Only affects ASTs.

aa2cac5edc v7.14.9
🚫 Release only.

b3ab4769d0 fix(ts): raise error for `export default interface {}` (#13622)
🚫 Validation only.

a254ea38a4 Enable ergonomic brand checks (`#priv in`) by default (#13554)
🚫 Already works by default in Sucrase.

6276853eb9 Add support for the "Hack" pipeline proposal (#13191)
🚫 Already works with Sucrase. This babel-parser change updates error handling (not relevant for Sucrase) and switches the default topic reference token to `%`, but more recent discussions have decided against that one.

cd4b3fbffe parser: Fix Hack/smart-pipe error positions (#13426)
🚫 AST only.

35e4e1f067 Hack-pipe proposal with `%` topic token (#13416)
🚫 Changes are only to AST, error handling, and `%` topic reference token support.

ff287ac5a5 Fix `%==` parsing in hack pipes (#13536)
🚫 Only affects outdated `%` topic reference tokens.

c35637e247 feat(ts): raise error for abstract property with initializer (#13523)
🚫 Validation only.

ddaf0d4296 Enable top-level `await` parsing by default (#13387)
🚫 Already enabled by default in Sucrase.

d5b0d9e33d Add `attachComment` parser option to disable comment attachment (#13229)
🚫 Not relevant to Sucrase.

0671afcf87 [ts] support optional chain call with generic (#13513)
🚫 Already works and has tests.

6912f968a6 v7.15.0
🚫 Release only.

f9dcc4e4bb Fix array destructuring elision parsing in TS arrow functions (#13641)
🚫 Regression that wasn't introduced in Sucrase.

e294beb3ac Add `.errors` to the `@babel/parser` return type definitions (#13653)
🚫 Type definitions only.

084870faad v7.15.2
🚫 Release only.

8a09993e39 fix(parser): add `attachComment` to `ParserOptions` type (#13657)
🚫 Type definitions only.

da1d166ea6 perf: minor tokenizer tweaks (#13652)
🚫 Optimizations not relevant to Sucrase.

9d0aa1ec9d Disallow `<T>(a => b)` when parsing Flow (#13645)
🚫 Validation only.

e721f61110 [flow] Fix parsing of arrows in conditional exprs in parens (#13655)
✅ Seems to be fixed by above fix. I added a regression test.

1229336fea Fix parse error when using named import "as" with flow parser (#13659)
✅ Added test and ported fix in fairly direct way.

9286cdb072 Re-enable disabled flow parser test (#13661)
🚫 Test only.

a5624ea457 v7.15.3
🚫 Test only.

10640b2aad perf: partially replace `.concat` with `.push` (#13609)
🚫 Sucrase doesn't use `.concat`.

Patch:
diff --git a/src/parser/plugins/flow.ts b/src/parser/plugins/flow.ts
index 6438a0f..834bcf5 100644
--- a/src/parser/plugins/flow.ts
+++ b/src/parser/plugins/flow.ts
@@ -933,9 +933,11 @@ export function flowParseImportSpecifier(): void {
       // `import {type as foo`
       parseIdentifier();
     }
-  } else if (isTypeKeyword && (match(tt.name) || !!(state.type & TokenType.IS_KEYWORD))) {
-    // `import {type foo`
-    parseIdentifier();
+  } else {
+    if (isTypeKeyword && (match(tt.name) || !!(state.type & TokenType.IS_KEYWORD))) {
+      // `import {type foo`
+      parseIdentifier();
+    }
     if (eatContextual(ContextualKeyword._as)) {
       parseIdentifier();
     }
diff --git a/src/parser/traverser/expression.ts b/src/parser/traverser/expression.ts
index 0dc0ad8..78e2c26 100644
--- a/src/parser/traverser/expression.ts
+++ b/src/parser/traverser/expression.ts
@@ -664,6 +664,15 @@ function parseParenAndDistinguishExpression(canBeArrow: boolean): boolean {
       parseFunctionParams();
       parseArrow();
       parseArrowExpression(startTokenIndex);
+      if (state.error) {
+        // Nevermind! This must have been something that looks very much like an
+        // arrow function but where its "parameter list" isn't actually a valid
+        // parameter list. Force non-arrow parsing.
+        // See https://github.com/alangpierce/sucrase/issues/666 for an example.
+        state.restoreFromSnapshot(snapshot);
+        parseParenAndDistinguishExpression(false);
+        return false;
+      }
       return true;
     }
   }


Test patch:
diff --git a/test/flow-test.ts b/test/flow-test.ts
index 1e7fe18..71a655f 100644
--- a/test/flow-test.ts
+++ b/test/flow-test.ts
@@ -479,4 +479,15 @@ describe("transform flow", () => {
       {disableESTransforms: true},
     );
   });
+
+  it("properly parses `as as` in an import statement", () => {
+    assertFlowResult(
+      `
+      import {foo as as} from "./Foo";
+    `,
+      `"use strict";
+      var _Foo = require('./Foo');
+    `,
+    );
+  });
 });
diff --git a/test/typescript-test.ts b/test/typescript-test.ts
index 087b279..e3d9ada 100644
--- a/test/typescript-test.ts
+++ b/test/typescript-test.ts
@@ -2844,4 +2844,30 @@ describe("typescript transform", () => {
       {disableESTransforms: true},
     );
   });
+
+  it("doesn't get confused by += within an arrow function in a ternary", () => {
+    // https://github.com/alangpierce/sucrase/issues/666
+    assertResult(
+      `
+      0 ? a => (a += 0) : a => 0
+    `,
+      `
+      0 ? a => (a += 0) : a => 0
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("doesn't get confused by parenthesized arrow/ternary combination", () => {
+    // Regression test for code from https://github.com/babel/babel/issues/13644
+    assertResult(
+      `
+      (a ? v => (sum += 1) : v => 0);
+    `,
+      `
+      (a ? v => (sum += 1) : v => 0);
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
 });