【编译技术】:解读 Babel AST Format——01

时间:2022-07-28
本文章向大家介绍【编译技术】:解读 Babel AST Format——01,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
目录
1. 什么是 Babel AST Format?
2. 本期涉及哪些 AST node types?
3. 语法规范回顾
    3.1. InterpreterDirective 是什么?
    3.2. Directive 是什么?
    3.3. Decorator 是什么?
4. 示例    

1. 什么是 Babel AST Format?

The Babel parser generates AST according to Babel AST format. It is based on ESTree spec with some deviations.

2. 本期涉及哪些 AST node types?

本期涉及:

  • Misc
    • Decorator
    • Directive
    • DirectiveLiteral
    • InterpreterDirective

注1:Misc 是 Miscellaneous 的缩写,代表杂项。

3. 语法规范回顾

3.1. InterpreterDirective 是什么?

示例:

#!:

  • #! 叫做“Shebang”或者“Sha-bang”。
  • Shebang 的名字来自于 SHArp 和 bang,或haSH bang的缩写,指代Shebang中#!两个符号的典型Unix名称。Unix术语中,井号通常称为sharp,hash或mesh;而叹号则常常称为bang。
  • Shebang通常出现在类Unix系统的脚本中第一行,作为前两个字符。

代码示例:(node_modules@babelparserbinbabel-parser.js)

#!/usr/bin/env node
/* eslint no-var: 0 */

var parser = require("..");
var fs = require("fs");

var filename = process.argv[2];
if (!filename) {
  console.error("no filename specified");
} else {
  var file = fs.readFileSync(filename, "utf8");
  var ast = parser.parse(file);

  console.log(JSON.stringify(ast, null, "  "));
}

AST Node:

  • Babylon already parses "shebangs" (#!env node) but put's in a comment in the Program node. Now we are just creating an actual node for it.
    • Add a new interpreter field to the Program node.
export interface Program extends BaseNode {
  type: "Program";
  body: Array<Statement>;
  directives: Array<Directive>;
  sourceType: "script" | "module";
  interpreter: InterpreterDirective | null;
  sourceFile: string;
}
export interface InterpreterDirective extends BaseNode {
  type: "InterpreterDirective";
  value: string;
}

3.2. Directive 是什么?

  • A Directive Prologue is the longest sequence of ExpressionStatement productions occurring as the initial StatementListItem or ModuleItem productions of a FunctionBody, a ScriptBody, or a ModuleBody and where each ExpressionStatement in the sequence consists entirely of a StringLiteral token followed by a semicolon. The semicolon may appear explicitly or may be inserted by automatic semicolon insertion. A Directive Prologue may be an empty sequence.
  • A Use Strict Directive is an ExpressionStatement in a Directive Prologue whose StringLiteral is either the exact code unit sequences "use strict" or 'use strict'. A Use Strict Directive may not contain an EscapeSequence or LineContinuation.

代码示例:

'use strict';

AST Node:

export interface Directive extends BaseNode {
  type: "Directive";
  value: DirectiveLiteral;
}

export interface DirectiveLiteral extends BaseNode {
  type: "DirectiveLiteral";
  value: string;
}

3.3. Decorator 是什么?

Decorators @decorator are functions called on class elements or other JavaScript syntax forms during definition, potentially wrapping or replacing them with a new value returned by the decorator.

代码示例:

@isTestable(true)
class MyClass { }
function isTestable(value) {}

AST Node:

export interface Decorator extends BaseNode {
  type: "Decorator";
  expression: Expression;
}

4. 示例

代码示例:

const parser = require("@babel/parser");

const code = `
'use strict';
@testable()
class MyApp{}
function testable() {}
`;

const node = parser.parse(code, {plugins: ["decorators-legacy"]});

console.log(JSON.stringify(node));

AST Nodes:

{
  "type": "File",
  "start": 0,
  "end": 64,
  "loc": {
    "start": {
      "line": 1,
      "column": 0
    },
    "end": {
      "line": 6,
      "column": 0
    }
  },
  "errors": [],
  "program": {
    "type": "Program",
    "start": 0,
    "end": 64,
    "loc": {
      "start": {
        "line": 1,
        "column": 0
      },
      "end": {
        "line": 6,
        "column": 0
      }
    },
    "sourceType": "script",
    "interpreter": null,
    "body": [{
      "type": "ClassDeclaration",
      "start": 15,
      "end": 40,
      "loc": {
        "start": {
          "line": 3,
          "column": 0
        },
        "end": {
          "line": 4,
          "column": 13
        }
      },
      "decorators": [{
        "type": "Decorator",
        "start": 15,
        "end": 26,
        "loc": {
          "start": {
            "line": 3,
            "column": 0
          },
          "end": {
            "line": 3,
            "column": 11
          }
        },
        "expression": {
          "type": "CallExpression",
          "start": 16,
          "end": 26,
          "loc": {
            "start": {
              "line": 3,
              "column": 1
            },
            "end": {
              "line": 3,
              "column": 11
            }
          },
          "callee": {
            "type": "Identifier",
            "start": 16,
            "end": 24,
            "loc": {
              "start": {
                "line": 3,
                "column": 1
              },
              "end": {
                "line": 3,
                "column": 9
              },
              "identifierName": "testable"
            },
            "name": "testable"
          },
          "arguments": []
        }
      }],
      "id": {
        "type": "Identifier",
        "start": 33,
        "end": 38,
        "loc": {
          "start": {
            "line": 4,
            "column": 6
          },
          "end": {
            "line": 4,
            "column": 11
          },
          "identifierName": "MyApp"
        },
        "name": "MyApp"
      },
      "superClass": null,
      "body": {
        "type": "ClassBody",
        "start": 38,
        "end": 40,
        "loc": {
          "start": {
            "line": 4,
            "column": 11
          },
          "end": {
            "line": 4,
            "column": 13
          }
        },
        "body": []
      }
    }, {
      "type": "FunctionDeclaration",
      "start": 41,
      "end": 63,
      "loc": {
        "start": {
          "line": 5,
          "column": 0
        },
        "end": {
          "line": 5,
          "column": 22
        }
      },
      "id": {
        "type": "Identifier",
        "start": 50,
        "end": 58,
        "loc": {
          "start": {
            "line": 5,
            "column": 9
          },
          "end": {
            "line": 5,
            "column": 17
          },
          "identifierName": "testable"
        },
        "name": "testable"
      },
      "generator": false,
      "async": false,
      "params": [],
      "body": {
        "type": "BlockStatement",
        "start": 61,
        "end": 63,
        "loc": {
          "start": {
            "line": 5,
            "column": 20
          },
          "end": {
            "line": 5,
            "column": 22
          }
        },
        "body": [],
        "directives": []
      }
    }],
    "directives": [{
      "type": "Directive",
      "start": 1,
      "end": 14,
      "loc": {
        "start": {
          "line": 2,
          "column": 0
        },
        "end": {
          "line": 2,
          "column": 13
        }
      },
      "value": {
        "type": "DirectiveLiteral",
        "start": 1,
        "end": 13,
        "loc": {
          "start": {
            "line": 2,
            "column": 0
          },
          "end": {
            "line": 2,
            "column": 12
          }
        },
        "value": "use strict",
        "extra": {
          "raw": "'use strict'",
          "rawValue": "use strict"
        }
      }
    }]
  },
  "comments": []
}

参考资料1:

Babel AST format: https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md ESTree spec: https://github.com/estree/estree ECMAScript® 2015 Language Specification: http://www.ecma-international.org/ecma-262/6.0/index.html

参考资料2:Directive

Add InterpreterDirective Node: https://babeljs.io/docs/en/v7-migration-api#add-interpreterdirective-node-7928httpsgithubcombabelbabelpull7928 Directive Prologues and the Use Strict Directive: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-directive-prologues-and-the-use-strict-directive

参考资料3:Decorator

https://babeljs.io/docs/en/babel-plugin-proposal-decorators https://github.com/tc39/proposal-decorators https://github.com/tc39/proposal-decorators/issues/69