Repository: babel/babel-eslint (JavaScript)

Issue:
Invalid token `type` field for nullish coalescing operator
The `type` field in the token should be a string (as [per spec](https://eslint.org/docs/developer-guide/working-with-plugins#the-ast-specification)) but it's an object instead.

Example:

```javascript
parser.parse('foo ?? bar')
```

```
Node {
  type: 'Program',
  start: 0,
  end: 10,
  loc:
   SourceLocation {
     start: Position { line: 1, column: 0 },
     end: Position { line: 1, column: 10 } },
  range: [ 0, 10 ],
  comments: [],
  tokens:
   [ Token {
       type: 'Identifier',
       value: 'foo',
       start: 0,
       end: 3,
       loc: [SourceLocation],
       range: [Array] },
     Token {
       type: [BinopTokenType],
       value: '??',
       start: 4,
       end: 6,
       loc: [SourceLocation],
       range: [Array] },
     Token {
       type: 'Identifier',
       value: 'bar',
       start: 7,
       end: 10,
       loc: [SourceLocation],
       range: [Array] } ],
  sourceType: 'module',
  directives: undefined,
  body:
   [ Node {
       type: 'ExpressionStatement',
       start: 0,
       end: 10,
       loc: [SourceLocation],
       range: [Array],
       expression: [Node],
       _babelType: 'ExpressionStatement' } ] }
```

This was noticed by the ESLint folks in [this PR](https://github.com/eslint/eslint/pull/10476#issuecomment-397140501).


Discussion:
This is also an issue for the pipeline and optional chaining operators.



Patch:
diff --git a/lib/babylon-to-espree/toToken.js b/lib/babylon-to-espree/toToken.js
index 082aef3e..44c73529 100644
--- a/lib/babylon-to-espree/toToken.js
+++ b/lib/babylon-to-espree/toToken.js
@@ -19,16 +19,19 @@ module.exports = function(token, tt, source) {
     type === tt.bracketR ||
     type === tt.ellipsis ||
     type === tt.arrow ||
+    type === tt.pipeline ||
     type === tt.star ||
     type === tt.incDec ||
     type === tt.colon ||
     type === tt.question ||
+    type === tt.questionDot ||
     type === tt.template ||
     type === tt.backQuote ||
     type === tt.dollarBraceL ||
     type === tt.at ||
     type === tt.logicalOR ||
     type === tt.logicalAND ||
+    type === tt.nullishCoalescing ||
     type === tt.bitwiseOR ||
     type === tt.bitwiseXOR ||
     type === tt.bitwiseAND ||


Test patch:
diff --git a/test/babel-eslint.js b/test/babel-eslint.js
index c066ed28..b0a2cd10 100644
--- a/test/babel-eslint.js
+++ b/test/babel-eslint.js
@@ -256,6 +256,36 @@ describe("babylon-to-espree", () => {
     parseAndAssertSame("export { foo as bar };");
   });
 
+  // Espree doesn't support the optional chaining operator yet
+  it("optional chaining operator (token)", () => {
+    const code = "foo?.bar";
+    var babylonAST = babelEslint.parseForESLint(code, {
+      eslintVisitorKeys: true,
+      eslintScopeManager: true,
+    }).ast;
+    assert.strictEqual(babylonAST.tokens[1].type, "Punctuator");
+  });
+
+  // Espree doesn't support the nullish coalescing operator yet
+  it("nullish coalescing operator (token)", () => {
+    const code = "foo ?? bar";
+    var babylonAST = babelEslint.parseForESLint(code, {
+      eslintVisitorKeys: true,
+      eslintScopeManager: true,
+    }).ast;
+    assert.strictEqual(babylonAST.tokens[1].type, "Punctuator");
+  });
+
+  // Espree doesn't support the pipeline operator yet
+  it("pipeline operator (token)", () => {
+    const code = "foo |> bar";
+    var babylonAST = babelEslint.parseForESLint(code, {
+      eslintVisitorKeys: true,
+      eslintScopeManager: true,
+    }).ast;
+    assert.strictEqual(babylonAST.tokens[1].type, "Punctuator");
+  });
+
   it.skip("empty program with line comment", () => {
     parseAndAssertSame("// single comment");
   });