esprima-dotnet icon indicating copy to clipboard operation
esprima-dotnet copied to clipboard

Incorrect parse tree during several destructing assignment statements parsing

Open KvanTTT opened this issue 7 years ago • 3 comments

Input

  • DestructuringAssignment.js from examples dir of ANTLR JavaScript grammar.
  • Code snippet from http://es6-features.org/#ArrayMatching
var [ a, , b ] = list
[ b, a ] = [ a, b ]

Expected

Parse tree should contain two statements:

{
  "Type": "Program",
  "Body": [
    {
      "Type": "VariableDeclaration",
      "Declarations": [
        {
          "Type": "VariableDeclarator",
          "Id": {
            "Type": "ArrayPattern",
            "Elements": [
              {
                "Type": "Identifier",
                "Name": "a",
                "Loc": {}
              },
              null,
              {
                "Type": "Identifier",
                "Name": "b",
                "Loc": {}
              }
            ],
            "Loc": {}
          },
          "Init": {
            "Type": "Identifier",
            "Name": "list",
            "Loc": {}
          },
          "Loc": {}
        }
      ],
      "Kind": "var",
      "Loc": {}
    },
    {
      "Type": "ExpressionStatement",
      "Expression": {
        "Left": {
          "Type": "ArrayPattern",
          "Elements": [
            {
              "Type": "Identifier",
              "Name": "b",
              "Loc": {}
            },
            {
              "Type": "Identifier",
              "Name": "a",
              "Loc": {}
            }
          ],
          "Loc": {}
        },
        "Right": {
          "Type": "ArrayExpression",
          "Elements": [
            {
              "Type": "Identifier",
              "Name": "a",
              "Loc": {}
            },
            {
              "Type": "Identifier",
              "Name": "b",
              "Loc": {}
            }
          ],
          "Loc": {}
        },
        "Loc": {}
      },
      "Loc": {}
    }
  ],
  "SourceType": "script",
  "Loc": {}
}

Just add semicolon ; to the end of the first line to get the correct output:

var [ a, , b ] = list;
[ b, a ] = [ a, b ]

Actual

Code parsed to the following parse tree with nonexistent MemberExpression and only a single declaration:

{
  "Type": "Program",
  "Body": [
    {
      "Type": "VariableDeclaration",
      "Declarations": [
        {
          "Type": "VariableDeclarator",
          "Id": {
            "Type": "ArrayPattern",
            "Elements": [
              {
                "Type": "Identifier",
                "Name": "a",
                "Loc": {}
              },
              null,
              {
                "Type": "Identifier",
                "Name": "b",
                "Loc": {}
              }
            ],
            "Loc": {}
          },
          "Init": {
            "Left": {
              "Type": "MemberExpression",
              "Object": {
                "Type": "Identifier",
                "Name": "list",
                "Loc": {}
              },
              "Property": {
                "Type": "SequenceExpression",
                "Expressions": [
                  {
                    "Type": "Identifier",
                    "Name": "b",
                    "Loc": {}
                  },
                  {
                    "Type": "Identifier",
                    "Name": "a",
                    "Loc": {}
                  }
                ],
                "Loc": {}
              },
              "Computed": true,
              "Loc": {}
            },
            "Right": {
              "Type": "ArrayExpression",
              "Elements": [
                {
                  "Type": "Identifier",
                  "Name": "a",
                  "Loc": {}
                },
                {
                  "Type": "Identifier",
                  "Name": "b",
                  "Loc": {}
                }
              ],
              "Loc": {}
            },
            "Loc": {}
          },
          "Loc": {}
        }
      ],
      "Kind": "var",
      "Loc": {}
    }
  ],
  "SourceType": "script",
  "Loc": {}
}

KvanTTT avatar Sep 19 '18 16:09 KvanTTT

By the way, I found the same issue exists in the official parser. See demo.

KvanTTT avatar Sep 19 '18 21:09 KvanTTT

Thanks, at least we won't have to expect it to find the fix there.

sebastienros avatar Sep 19 '18 21:09 sebastienros

I also created an issue in esprima project tracker.

KvanTTT avatar Sep 20 '18 09:09 KvanTTT

Did some investigation and it seems to me that either this is a non-issue or everyone got it wrong. Both acorn and @babel/parser parse this as a single statement in AstExplorer. According to the output both Firefox and Chrome treat it as a single statement as well (both in legacy and strict mode):

// using octals to make sure we're not in strict mode
var list = [03, 04, 05];

(() => {
var [ a, , b ] = list
[ b, a ] = [ a, b ]
  
  console.log(`a: ${a}`, `b: ${b}`);
})();

(() => {
  'use strict';
  
var [ a, , b ] = list
[ b, a ] = [ a, b ]

  console.log(`a: ${a}`, `b: ${b}`);
})();

which logs

a: undefined b: undefined
a: undefined b: undefined

instead of the expected a: 5, b: 3

Am I missing here something or can we close this?

adams85 avatar Feb 25 '23 14:02 adams85

Maybe just close and we can reopen if there's a repro against other parser.

lahma avatar Feb 25 '23 14:02 lahma