babel AST

Babel Plugin Manual AST inspection tool: AstExplorer.net Complete AST definition

Literal

  • NumbericLiteral
  • StringLiteral
  • BooleanLiteral
  • RegExpLiteral
  • TemplateLiteral eg: `ll`
  • BiginLiteral eg: 1.2324 n
  • NullLiteral

Identifier

Variable names, attribute names, parameter names, and various declaration and reference names

Statement

A unit that can be executed independently. Each piece of independently executed code is characteristic of a statement. Or a newline

// BreakStatement break; // ContunueStatement continue; // ReturnStatement return; // DebuggerStatement debugger; // ThrowStatement throw Error(); // BlockStatement {} // TryStatement try {} catch(e) {} finally{} // ForinStatement for (let key in obj) {} // ForStatement for (let i = 0; i < 10; i ++) {} // WhileStatement while (true) {} // DoWhileStatement do {} while (true) // SwitchStatement switch (v){case 1: break; default:; } // LabeledStatement label: console.log(); // WithStatement with (a){}Copy the code

Declaration

A declarative statement is a special statement that performs logic to declare a variable, function, class, import, export, and so on in scope

// VariableDeclaration
const a = 1;
// FunctionDeclaration
function b(){}
// ClassDeclaration
class C {}
// ImportDeclaration
import d from 'e';
// ExportDefaultDeclaration
export default e = 1;
// ExportNameDeclaration
export {e};
// ExportAllDeclaration
export * from 'e';
Copy the code

Expression

Expressions that return values after execution, and expressions that can be independently executed as statements that wrap a layer of ExpressionStatement

// ArrayExpression [1,2,3] // AssignmentExpression a = 1 // BinaryExpression 1 + 2; // UnaryExpression -1; // FunctionExpression function(){}; // ArrowFunctionExpression () => {}; // ClassExpression class{}; // Identifier a; // ThisExpression this; // Super super; // BindExpression a::b;Copy the code

Class

ClassBody attribute: ClassProperty Method: constructor or method

// ClassDectaration
class Guang extends Person{
    // ClassProperty
    name = 'guang';
    // ClassMethod (kind='constructor')
    constructor() {}
    // // ClassMethod(kind='method')
    eat() {}
}
Copy the code

import

The specifiers in the ImportDeclaration node have different attributes

// ImportDeclaration
// d--> ImportDefaultSpecifier
import d from 'e';
// ImportDeclaration
// c,d --> ImportSpicifier
import {c, d} from 'c';
// ImportDeclaration
// * as b --> ImportNamespaceSpcifier
import * as b from 'b';

Copy the code

export

// ExportNamedDeclaration
// b, d --> ExportSpecifier
export { b, d};
// ExportDefaultDeclaration
export default a;
//ExportAllDeclaration 
export * from 'c';
Copy the code

Program & Directive

Program is a node that represents the entire program. It has the body attribute to represent the body of the program and stores the statement array, which is a collection of specific statements to be executed. And the directives property, which holds the Directive node, such as “use strict” directives that use the Directive node.

/*
 *               Program
 *      body  /         \ directives
 *           /           \
 *  callExpression   Directive
 *  callExpression 
*/

"use strict"
console.log(1);
console.log(2);
Copy the code

File & Comment

The outermost layer of Babel’s AST is File. It contains Program, Comments, tokens and other attributes

  • commentBlock
/*
* ll
*/
Copy the code
  • CommentLine
// ll
Copy the code

Babel api

@babel/parse

  • The parse AST root node is File
  • The root node returned by parseExpression is Expression
function parse(input: string, options? : ParserOptions): File function parseExpression(input: string, options? : ParserOptions): ExpressionCopy the code

@bable/traverse

// parent specifies the AST node to traverse // opts specifies the visitor function. Babel calls the appropriate visitor function while iterating through the PARENT's AST. function traverse(parent, opts)Copy the code

The value of the visitor object is an object or function:

  • If value is a function, then it is the same function that was called when Enter.
  • If value is an object, you can explicitly specify the handler for Enter or exit.
visitor: {
    Identifier (path, state) {},
    StringLiteral: {
        enter (path, state) {},
        exit (path, state) {}
    }
}
Copy the code

path

Path {// attributes: // Point to the current AST node node // Parent AST node parent // Path of parent AST node parentPath // Obtain the scope information of the current node scope // The outermost layer can be obtained through path.hub.file File object, Path.hub. getScope Gets the value of the parent of the outermost scope hub // Container // Name of the parent of the current AST node or subscript key of the array // Current AST If the value of the parent node property of the node is array, listKey is the name of the property. // Set (key, node) // Check whether the node is in an array. If container is an array, So when I have a listkey, Return true inList() // get a subscript sibling getSibling(key) // get the next sibling getNextSibling() // get the last sibling getPrevSibling() // GetAllPrevSiblings () getGetSiblings () getAllNextSiblings() getGetSiblings () getGetSiblings () getGetSiblings () getGetSiblings () Such as path. IsIdentifier ({name: 'a'}) isXxx(opts) // same as isXxx, but does not return a Boolean value, but throws an exception assertXxx(opts) // insertBefore the node, either a single node or an array of nodes insertBefore // After the node, Can be a single node or an array of nodes insertAfter(nodes) // replace the current node with a node replaceWith(replacement) // Replace the current node with multiple (nodes) // ReplaceWithSourceString (replacement) // Remove the current node remove() // iterate over the children of the current node, Pass visitor and state (state is how data is passed between different nodes) traverse(visitor, state) // skip() // stop()}Copy the code

Path. scope Scope information

Path. scope {// All variables declared in the current scope // generate scope block block // information of the parent scope parent // block node corresponding to the parent scope parentBlock // generate scope node corresponding to Dump () // Block parentBlock() of the parent scope GetBinding (name) = getBinding(name); getBinding(name) = getBinding(name); HasBinding (name, noGlobals) // Find a binding from the current scope. GetOwnBinding (name) // Find a binding from the parent scope to the root scope. Does not include the current scope. You can specify whether global variables are included with the noGlobals parameter (such as console, which is undeclared), ParentHasBinding (name, MoveBindingTo (name, scope) moveBindingTo(name, scope) GenerateUid (name)} generateUid(name) {generateUid(name)}Copy the code

scope.block

Pass path.scope.block to get the node corresponding to the block, pass path.scope.parentBlock to get the block node corresponding to the parent scope. Path. scope gets scope information, and patsh.scope.parent gets parent scope information

// scope block,  export type Scopable = | BlockStatement | CatchClause | DoWhileStatement | ForInStatement | ForStatement | FunctionDeclaration | FunctionExpression | Program | ObjectMethod | SwitchStatement | WhileStatement | ArrowFunctionExpression | ClassExpression | ClassDeclaration | ForOfStatement | ClassMethod | ClassPrivateMethod | StaticBlock | TSModuleBlock;Copy the code

Scope. The bindings and scope. The references

Every binding has a kind, which represents the type of binding:

  • Var, let, and const represent variables declared in var, let, and const forms, respectively
  • Param stands for declaration of parameters
  • Module represents the declaration of the variable import
const a = 1; Bindings: {a: {// indicates whether the variable has been modified constant: True, // If changed, you can get the path of all changed statements by binding. ConstViolations: [], // AST, identifier: {type: 'Identifier', ... } kind:'const', // AST path: {node,... } // If the variable is referenced: false // If it is referenced, get the path referencePaths for all the quoted statements by using binding.referencepaths: [], references: 0, scope: ... }}Copy the code

Node chain, Block chain, scope chain

There are three chains starting from a node

  • The AST node chain connected by path and path.parent,
  • Path.scope and path.scope. Parent are connected by the scope chain,
  • Path.scope. block and path.scope.parentBlock serial block AST block chain.

state

A mechanism for passing data between different nodes during traversal

State {// File level information, or file // plugin configuration item opts from path.hub.file}Copy the code

AST alias

/ / a single AST type FunctionDeclaration (path, state) {}, / / multiple AST type 'FunctionDeclaration | VariableDeclaration' (path, State){// AST type alias Declaration(){}Copy the code

SourceMap

format

{// source map version number version: 3, // Converted file name file: "outname. js", // saved file before conversion. If the input and output files are in the same directory sourceRoot: "", // the file before conversion. Sources: ["inputName1.js", "inputName2.js"], // All variable names and attribute names before conversion: [" SRC ", "maps", "are", "fun"], // String mappings with location information: "XXXXX, XXXX, XXXXXX"}Copy the code

mappings

  • The first, which indicates the number of columns in the transformed code in which this position is located.
  • The second, indicating which file the location belongs to in the Sources property.
  • The third bit, indicating which line of code this position belongs to before the conversion.
  • The fourth bit, which indicates the number of columns in the code before the transformation.
  • The fifth digit, indicating which variable in the NAMES property this position belongs to. Do not necessarily have

source-map

Sourcemap source-map exposes the SourceMapConsumer, SourceMapGenerator, and SourceNode classes for generating and parsing sourcemap source-Map. They are used to consume sourcemap, generate sourcemAP, and create source nodes. == Generation process == :

  1. Create a SourceMapGenerator object
  2. Add a mapping using the addMapping method
  3. To sourcemap string via toString

@babel/types

Create an AST and determine the AST type

@babel/template

Create AST nodes in batches

@babel/generator

The AST is then printed as an object code string

@babel/code-frame

Print error message

@babel/core

Complete the whole compilation process based on @babel/core, from source code to object code, and generate sourcemap.

generate

Built-in Babel features

  • Compat-table provides versioning support for each feature in different environments
  • electron-to-chromium
    • Mapping from the ELECTRON version to the Chromium version
    • Chromium version is used in electron version.
  • @babel/compat-data
    • Version support for features implemented by the Plugin
    • Version support for the feature polyfill by Corejs.

browerslist

  • Browerslist Query provides a conversion from Query (query expression) to the corresponding version of the environment.

@babel/plugin-transform-runtime

Change direct global injection to modular import.

practice

Basic practice of Babel, git address github.com/liling0726/…

conclusion

This article is basically organized according to the secret book of Babel and many articles of gold diggers as reference. The understanding of Babel is still in the theoretical stage, and the practical part will be improved later

reference

  • Babel: Architecture and Principles + Practice
  • Manual of the Babel plug-in