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

2020-11-05 10:39:04 浏览数 (1)

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?

本期涉及:

  • Expressions
    • Super
    • Import
    • ThisExpression
    • ArrowFunctionExpression
    • YieldExpression
    • AwaitExpression
    • ArrayExpression
    • ObjectExpression
      • ObjectMember
        • ObjectProperty
        • ObjectMethod
    • RecordExpression
    • TupleExpression
    • FunctionExpression
    • Unary operations
      • UnaryExpression
        • UnaryOperator
      • UpdateExpression
        • UpdateOperator
    • Binary operations
      • BinaryExpression
        • BinaryOperator
      • AssignmentExpression
        • AssignmentOperator
      • LogicalExpression
        • LogicalOperator
      • SpreadElement
      • ArgumentPlaceholder
      • MemberExpression
      • BindExpression
    • ConditionalExpression
    • CallExpression
    • NewExpression
    • SequenceExpression
    • ParenthesizedExpression
    • DoExpression

3. 示例

3.1. Super

AST:A super pseudo-expression.

代码语言:javascript复制
export interface Super extends BaseNode {
  type: "Super";
}

示例:

代码语言:javascript复制
class App extends React.Component{
    constructor(props){
        super(props);
    }
}

3.2. Import

AST:A import pseudo-expression.

代码语言:javascript复制
export interface Import extends BaseNode {
  type: "Import";
}

示例:

代码语言:javascript复制
import("lodop");

3.3. ThisExpression

AST:A this expression.

代码语言:javascript复制
export interface ThisExpression extends BaseNode {
  type: "ThisExpression";
}

示例:

代码语言:javascript复制
function Person(){
    this.xm = "John";
}

3.4. ArrowFunctionExpression

AST:A fat arrow function expression, e.g., let foo = (bar) => { /* body */ }.

代码语言:javascript复制
export interface Import extends BaseNode {
  type: "Import";
}

示例:

代码语言:javascript复制
() => {}

3.5. YieldExpression

AST:A yield expression.

代码语言:javascript复制
export interface YieldExpression extends BaseNode {
  type: "YieldExpression";
  argument: Expression | null;
  delegate: boolean;
}

示例:

代码语言:javascript复制
function* fn(){
    yield 3;
}

3.6. AwaitExpression

AST:A await expression.

代码语言:javascript复制
export interface AwaitExpression extends BaseNode {
  type: "AwaitExpression";
  argument: Expression;
}

示例:

代码语言:javascript复制
async function fn(){
    await 3;
}

3.7. ArrayExpression

AST:An array expression..

代码语言:javascript复制
export interface ArrayExpression extends BaseNode {
  type: "ArrayExpression";
  elements: Array<null | Expression | SpreadElement>;
}

示例:

代码语言:javascript复制
[1, 2, 3]

3.8. ObjectExpression

AST:An object expression.

代码语言:javascript复制
export interface ObjectExpression extends BaseNode {
  type: "ObjectExpression";
  properties: Array<ObjectMethod | ObjectProperty | SpreadElement>;
}

export interface ObjectMethod extends BaseNode {
  type: "ObjectMethod";
  kind: "method" | "get" | "set";
  key: Expression | Identifier | StringLiteral | NumericLiteral;
  params: Array<Identifier | Pattern | RestElement | TSParameterProperty>;
  body: BlockStatement;
  computed: boolean;
  generator: boolean;
  async: boolean;
  decorators: Array<Decorator> | null;
  returnType: TypeAnnotation | TSTypeAnnotation | Noop | null;
  typeParameters: TypeParameterDeclaration | TSTypeParameterDeclaration | Noop | null;
}

export interface ObjectProperty extends BaseNode {
  type: "ObjectProperty";
  key: Expression | Identifier | StringLiteral | NumericLiteral;
  value: Expression | PatternLike;
  computed: boolean;
  shorthand: boolean;
  decorators: Array<Decorator> | null;
}

export interface RestElement extends BaseNode {
  type: "RestElement";
  argument: LVal;
  decorators: Array<Decorator> | null;
  typeAnnotation: TypeAnnotation | TSTypeAnnotation | Noop | null;
}

示例:

代码语言:javascript复制
({
    xm: "John",
    getXm(){
    },
    ...props,
})

3.9. RecordExpression

3.10. TupleExpression

proposal-record-tuple:

  • This proposal introduces two new deeply immutable data structures to JavaScript:
    • Record, a deeply immutable Object-like structure #{ x: 1, y: 2 }
    • Tuple, a deeply immutable Array-like structure #[1, 2, 3, 4]
  • Records and Tuples can only contain primitives and other Records and Tuples. You could think of Records and Tuples as "compound primitives". By being thoroughly based on primitives, not objects, Records and Tuples are deeply immutable.
  • Records and Tuples support comfortable idioms for construction, manipulation and use, similar to working with objects and Arrays. They are compared deeply by their contents, rather than by their identity.

AST:

代码语言:javascript复制
export interface RecordExpression extends BaseNode {
  type: "RecordExpression";
  properties: Array<ObjectProperty | SpreadElement>;
}

export interface TupleExpression extends BaseNode {
  type: "TupleExpression";
  elements: Array<Expression | SpreadElement>;
}

3.11. FunctionExpression

AST:A function expression.

代码语言:javascript复制
export interface FunctionExpression extends BaseNode {
  type: "FunctionExpression";
  id: Identifier | null;
  params: Array<Identifier | Pattern | RestElement | TSParameterProperty>;
  body: BlockStatement;
  generator: boolean;
  async: boolean;
  returnType: TypeAnnotation | TSTypeAnnotation | Noop | null;
  typeParameters: TypeParameterDeclaration | TSTypeParameterDeclaration | Noop | null;
}

示例:

代码语言:javascript复制
const fn = function(){}

3.12. Unary operations——UnaryExpression

AST:A unary operator expression.

代码语言:javascript复制
export interface UnaryExpression extends BaseNode {
  type: "UnaryExpression";
  operator: "void" | "throw" | "delete" | "!" | " " | "-" | "~" | "typeof";
  argument: Expression;
  prefix: boolean;
}

示例:

代码语言:javascript复制
 3;

3.13. Unary operations——UpdateExpression

AST:An update (increment or decrement) operator expression.

代码语言:javascript复制
export interface UpdateExpression extends BaseNode {
  type: "UpdateExpression";
  operator: "  " | "--";
  argument: Expression;
  prefix: boolean;
}

示例:

代码语言:javascript复制
x  ;

3.14. Binary operations——BinaryExpression

AST:A binary operator expression.

代码语言:javascript复制
export interface BinaryExpression extends BaseNode {
  type: "BinaryExpression";
  operator: " " | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>" | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof" | ">" | "<" | ">=" | "<=";
  left: Expression | PrivateName;
  right: Expression;
}

示例:

代码语言:javascript复制
x   y

3.15. Binary operations——AssignmentExpression

AST:An assignment operator expression. It has short-circuiting behaviour if the operator is one of "||=", "&&=", and "??=".

代码语言:javascript复制
export interface AssignmentExpression extends BaseNode {
  type: "AssignmentExpression";
  operator: string;
  left: LVal;
  right: Expression;
}
enum AssignmentOperator {
  "=" | " =" | "-=" | "*=" | "/=" | "%=" | "**="
    | "<<=" | ">>=" | ">>>="
    | "|=" | "^=" | "&="
    | "||=" | "&&=" | "??="
}

示例:

代码语言:javascript复制
x  = 2;

3.16. Binary operations——LogicalExpression

AST:A logical operator expression.

代码语言:javascript复制
export interface LogicalExpression extends BaseNode {
  type: "LogicalExpression";
  operator: "||" | "&&" | "??";
  left: Expression;
  right: Expression;
}

示例:

代码语言:javascript复制
x && y

3.17. Binary operations——SpreadElement

AST:A logical operator expression.

代码语言:javascript复制
export interface SpreadElement extends BaseNode {
  type: "SpreadElement";
  argument: Expression;
}

示例:

代码语言:javascript复制
[...x, ...y]

3.18. Binary operations——ArgumentPlaceholder

proposal-partial-application:

  • This proposal introduces a new syntax using the ? token in an argument list which allows you to partially apply an argument list to a call expression by acting as a placeholder for an argument.
  • The ? placeholder token can be supplied one or more times at the top level of the Arguments of a CallExpression, CallMemberExpression, or SuperCall (e.g. f(?) or o.f(?)), or in place of the Expression of a TemplateMiddleList (e.g. f`before${?}after`). ? is not an expression, rather it is a syntactic element that indicates special behavior (much like how `...` AssignmentExpression indicates spread, yet is itself not an expression).
  • The ? placeholder token can only be used in an argument list of a call expression, or as the only token in a placeholder of a template expression or tagged template expression. When present, the result of the call is a new function with a parameter for each ? token in the argument list. Any non-placeholder expression in the argument list becomes fixed in its position.
代码语言:javascript复制
function add(x, y) { return x   y; }

const addOne = add(1, ?); // apply from the left
addOne(2); // 3

const addTen = add(?, 10); // apply from the right
addTen(2); // 12  

AST:

代码语言:javascript复制
export interface ArgumentPlaceholder extends BaseNode {
  type: "ArgumentPlaceholder";
}

示例:

代码语言:javascript复制
const g = f(?, 1, ?);

3.19. Binary operations——MemberExpression

AST:A member expression. If computed is true, the node corresponds to a computed (a[b]) member expression and property is an Expression. If computed is false, the node corresponds to a static (a.b) member expression and property is an Identifier or a PrivateName.

代码语言:javascript复制
export interface MemberExpression extends BaseNode {
  type: "MemberExpression";
  object: Expression;
  property: Expression | Identifier | PrivateName;
  computed: boolean;
  optional: true | false | null;
}

示例:

代码语言:javascript复制
a.b;
a[b];

3.20. Binary operations——BindExpression

ES7:

  • Babel 5.4 was just released and with it comes support for a new experimental ES7 syntax proposed by Kevin Smith (@zenparsing) and implemented in Babel by Ingvar Stepanyan (@RReverser).
  • The function bind syntax introduces a new operator :: which performs function binding and method extraction.
  • The function bind syntax introduces a new operator :: which performs function binding and method extraction.

ES7——Demo:

代码语言:javascript复制
经典写法:
  [].map.call(someNodeList, myFn);
  Array.from(someNodeList).map(myFn);
ES7写法:
  someNodeList::map(myFn);  

AST:

  • If object is null, then callee should be a MemberExpression.
代码语言:javascript复制
export interface BindExpression extends BaseNode {
  type: "BindExpression";
  object: Expression;
  callee: Expression;
}

示例:

代码语言:javascript复制
a::b

3.21. ConditionalExpression

AST:A conditional expression, i.e., a ternary ?/: expression.

代码语言:javascript复制
export interface ConditionalExpression extends BaseNode {
  type: "ConditionalExpression";
  test: Expression;
  consequent: Expression;
  alternate: Expression;
}

示例:

代码语言:javascript复制
a ? b : c

3.22. CallExpression

AST:A function or method call expression. When the callee is Import, the arguments must have only one Expression element.

代码语言:javascript复制
export interface CallExpression extends BaseNode {
  type: "CallExpression";
  callee: Expression | V8IntrinsicIdentifier;
  arguments: Array<Expression | SpreadElement | JSXNamespacedName | ArgumentPlaceholder>;
  optional: true | false | null;
  typeArguments: TypeParameterInstantiation | null;
  typeParameters: TSTypeParameterInstantiation | null;
}

示例:

代码语言:javascript复制
fn()

3.23. NewExpression

AST:A new expression.

代码语言:javascript复制
export interface NewExpression extends BaseNode {
  type: "NewExpression";
  callee: Expression | V8IntrinsicIdentifier;
  arguments: Array<Expression | SpreadElement | JSXNamespacedName | ArgumentPlaceholder>;
  optional: true | false | null;
  typeArguments: TypeParameterInstantiation | null;
  typeParameters: TSTypeParameterInstantiation | null;
}

示例:

代码语言:javascript复制
new App(1, 2)

3.24. SequenceExpression

AST:A sequence expression, i.e., a comma-separated sequence of expressions.

代码语言:javascript复制
export interface SequenceExpression extends BaseNode {
  type: "SequenceExpression";
  expressions: Array<Expression>;
}

示例:

代码语言:javascript复制
a,b,c,d;

3.24. ParenthesizedExpression

AST:An expression wrapped by parentheses. By default @babel/parser does not create this node, unless the createParenthesizedExpressions: true option is passed.

代码语言:javascript复制
export interface ParenthesizedExpression extends BaseNode {
  type: "ParenthesizedExpression";
  expression: Expression;
}

示例:

代码语言:javascript复制
//TODO 暂时还不太理解是干啥的

3.25. DoExpression

proposal-do-expressions:

  • The do { .. } expression executes a block (with one or many statements in it), and the final statement completion value inside the block becomes the completion value of the do expression.
  • One of the most useful usage of the do expression is inside JSX. If we want to conditionally display a component we usually have to call another function which would implement the condition and return the correct value, for example:
代码语言:javascript复制
const getColoredComponent = color => {
  if(color === 'blue') { return <BlueComponent/>; }
  if(color === 'red') { return <RedComponent/>; }
  if(color === 'green') { return <GreenComponent/>; }
}

const Component = props =>
  <div className='myComponent'>
    {getColoredComponent()}
  </div>
;

// Using a do expression you can add logic inside JSX:

const Component = props =>
  <div className='myComponent'>
    {do {
      if(color === 'blue') { <BlueComponent/>; }
      else if(color === 'red') { <RedComponent/>; }
      else if(color === 'green') { <GreenComponent/>; }
    }}
  </div>
;

AST:

代码语言:javascript复制
export interface DoExpression extends BaseNode {
  type: "DoExpression";
  body: BlockStatement;
}

示例:

代码语言:javascript复制
let a = do {
  if(x > 10) {
    'big';
  } else {
    'small';
  }
};

参考资料1:

Expressions: https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md#expressions Function Bind Syntax: https://babeljs.io/blog/2015/05/14/function-bind do-expressions: https://github.com/tc39/proposal-do-expressions https://babeljs.io/docs/en/babel-plugin-proposal-do-expressions

参考资料2:

Partial Application Syntax for ECMAScript: https://github.com/tc39/proposal-partial-application JavaScript Records & Tuples Proposal: https://github.com/tc39/proposal-record-tuple

0 人点赞