What is JavaScript AST, how to play with it?
Asked Answered
B

6

80

Abstract Syntax Tree.. I always heard that compile to SpiderMonkey AST on Github.
So, is that a actual standard of JS syntax tree? And there's V8, is V8 using the same kind of AST?

How can I play with that?

Bertberta answered 21/4, 2013 at 4:28 Comment(1)
Here's a handy visualization of javascript AST execution: int3.github.io/metajsToomay
W
33

SpiderMonkey offers the parser api. This is probably the easiest way to get your hands on the syntax objects.

There's also open js-js parsers like Esprima (which is ECMAScript, really, but it's right up the alley)

Walsh answered 21/4, 2013 at 4:36 Comment(0)
T
73

1.You can take a look at AST explorer. An online tool to explore the ASTs generated by more than 10 parsers. It is a good tool to learn AST tree of a language.
AST explorer source at Github.com.

enter image description here


2.Also you can paste your js code into JavaScript AST visualizer and click "show ast" button, you will see the AST visully.

demo js code:

function foo(d) {
  d += 3;
    return d+999
}
function bar(d) {
    return d*100
}

js ast demo

Twentyone answered 13/4, 2015 at 5:35 Comment(1)
what is the benefit of this image? Is it helpful?Dye
W
33

SpiderMonkey offers the parser api. This is probably the easiest way to get your hands on the syntax objects.

There's also open js-js parsers like Esprima (which is ECMAScript, really, but it's right up the alley)

Walsh answered 21/4, 2013 at 4:36 Comment(0)
E
15

Abstract Syntax Tree (AST), is a tree representation of program source code.

There is a couple JavaScript AST standards:

Here is a list of JavaScript parsers:

You can find more parsers on astexplorer.net, most of them estree compatible.

While most parsers that supports estree can be easily replaced by each other, babel has very rich infrastructure needed to comfortable work with AST. It has:

  • handbook describing all the tools, and ways to use it.
  • @babel/traverse - maintains the overall tree state, and is responsible for replacing, removing, and adding nodes;
  • @babel/template - simplest way to create a AST-node from string.
  • @babel/types - contains builders and checkers of AST-nodes.

One of the simplest way to play with AST, is using putout, which is based on babel and supports simplified way of transforming JavaScript code with help of plugins API.

Here is example of removing DebuggerStatement node:

module.exports.replace = () => ({
    'debugger': '',
});

If you want switch places of variables, changing the way of declaration:

module.exports.replace = () => ({
    'let __a = __b': 'const __b = __a'
});

If you want transform this code into return x[0]:

for (const x of y) {
    return x;
}

You can use:

module.exports.replace = () => ({
    'for (const __a of __b) {return __a}': 'return __a[0]',
});

With help of putout you can make simplest transformation of JavaScript code without handling with AST directly.

Euryale answered 14/2, 2021 at 9:42 Comment(1)
i have raised an issue with the nodejs team for a status follow up with tc9 proposal. pls vote and support his feature status request in the github issue i raised if you think this should be a feature in the nodejs. the feature is available in python. github.com/nodejs/node/issues/45158Danyelldanyelle
M
4

If you would like to try out the acron parser from professor Marijnh https://github.com/marijnh try out this link: https://astexplorer.net/

This is a tiny, fast JavaScript parser, written completely in JavaScript.

The above-mentioned JavaScript AST visualizer uses Esprima engine and has been also written in JavaScrpt.

JavaScript dominates in parsing AST because JavaScript engines are super optimized today. https://en.wikipedia.org/wiki/JavaScript_engine

SpiderMonkey AST standard of JS syntax tree? Is V8 using the same kind of AST?

Both of these web browser engines do have AST processing inside written in C++. This is why JavaScrpt code will run fast in most cases except for eval.

Margemargeaux answered 25/10, 2016 at 12:11 Comment(2)
the video link is invalidMathieu
Thanks @JuanPicado, I removed the link.Margemargeaux
D
1

I know only of one specification of Javascript AST: https://github.com/estree/estree

It originated from publication of Dave Herman from Mozilla and since then evolved as community standard. So it should match SpiderMonkey at some degree but I'm not sure about V8 and JSC.

Would appreciate if someone could provide more information on the matter.

Dike answered 13/8, 2019 at 10:51 Comment(0)
T
0

A JavaScript Abstract Syntax Tree (AST) is a hierarchical tree representation of the structure of JavaScript code. Each node in the tree represents a syntactic construct in the source code, such as expressions, statements, and declarations. ASTs are used extensively in compilers, interpreters, code analyzers, and transformation tools to understand and manipulate code.

Key Concepts of AST

  1. Nodes: Each node represents a construct in the code (e.g., a function, a variable declaration).

  2. Tree Structure: Nodes are connected in a parent-child relationship, representing the nested structure of the code.

Example Workflow

  1. Parse JavaScript Code to AST

  2. Traverse and Manipulate the AST

  3. Generate Code from AST

Using ASTs, you can parse, analyze, and manipulate JavaScript code programmatically. Tools like Acorn and Estraverse allow you to traverse and modify the AST, while tools like Escodegen can generate code from the modified AST. This approach is fundamental in building tools for code analysis, transformation, and optimization.

Original JavaScript Code

The AST corresponds to the following JavaScript code:

const greet = (name) => {
  return `Hello, ${name}!`;
};
console.log(greet('Suresh'));

JavaScript Code into an AST

  {
  "type": "Program",
  "start": 0,
  "end": 86,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 56,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 6,
          "end": 55,
          "id": {
            "type": "Identifier",
            "start": 6,
            "end": 11,
            "name": "greet"
          },
          "init": {
            "type": "ArrowFunctionExpression",
            "start": 14,
            "end": 55,
            "id": null,
            "expression": false,
            "generator": false,
            "async": false,
            "params": [
              {
                "type": "Identifier",
                "start": 15,
                "end": 19,
                "name": "name"
              }
            ],
            "body": {
              "type": "BlockStatement",
              "start": 24,
              "end": 55,
              "body": [
                {
                  "type": "ReturnStatement",
                  "start": 28,
                  "end": 53,
                  "argument": {
                    "type": "TemplateLiteral",
                    "start": 35,
                    "end": 52,
                    "expressions": [
                      {
                        "type": "Identifier",
                        "start": 45,
                        "end": 49,
                        "name": "name"
                      }
                    ],
                    "quasis": [
                      {
                        "type": "TemplateElement",
                        "start": 36,
                        "end": 43,
                        "value": {
                          "raw": "Hello, ",
                          "cooked": "Hello, "
                        },
                        "tail": false
                      },
                      {
                        "type": "TemplateElement",
                        "start": 50,
                        "end": 51,
                        "value": {
                          "raw": "!",
                          "cooked": "!"
                        },
                        "tail": true
                      }
                    ]
                  }
                }
              ]
            }
          }
        }
      ],
      "kind": "const"
    },
    {
      "type": "ExpressionStatement",
      "start": 57,
      "end": 86,
      "expression": {
        "type": "CallExpression",
        "start": 57,
        "end": 85,
        "callee": {
          "type": "MemberExpression",
          "start": 57,
          "end": 68,
          "object": {
            "type": "Identifier",
            "start": 57,
            "end": 64,
            "name": "console"
          },
          "property": {
            "type": "Identifier",
            "start": 65,
            "end": 68,
            "name": "log"
          },
          "computed": false,
          "optional": false
        },
        "arguments": [
          {
            "type": "CallExpression",
            "start": 69,
            "end": 84,
            "callee": {
              "type": "Identifier",
              "start": 69,
              "end": 74,
              "name": "greet"
            },
            "arguments": [
              {
                "type": "Literal",
                "start": 75,
                "end": 83,
                "value": "Suresh",
                "raw": "'Suresh'"
              }
            ],
            "optional": false
          }
        ],
        "optional": false
      }
    }
  ],
  "sourceType": "module"
}
Toffeenosed answered 8/7 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.