$30 off During Our Annual Pro Sale. View Details »

Let’s try to hack AST of JavaScript

sota ohara
July 06, 2019
1.4k

Let’s try to hack AST of JavaScript

sota ohara

July 06, 2019
Tweet

Transcript

  1. 1
    Let’s try to hack AST of JavaScript
    Sota Ohara
    2019.7.4 Battle Conference U30

    View Slide

  2. 2
    Tech Lead @ Mercari inc.
    Twitter: @sottar_
    GitHub: @sottar
    Sota Ohara

    View Slide

  3. 3
    - Introduce the AST
    - Create babel plugin
    Index

    View Slide

  4. 4
    What’s an AST

    View Slide

  5. 5
    Abstract Syntax Tree (抽象構文木)

    View Slide

  6. 6
    What’s an AST
    An AST is the result of parsing source code.
    A tree data structure which extracted necessary information from
    the source code
    DOM Tree is one of them
    Used for analysis and processing the source code
    It’s using by the compiler and interpreter

    View Slide

  7. 7
    It seems difficult...

    View Slide

  8. 8
    JavaScript AST

    View Slide

  9. 9
    JavaScript AST is not difficult
    We can use AST easily in JavaScript
    What’s a JavaScript AST?

    View Slide

  10. 10
    Just a JavaScript Object which displays an architecture of code
    What’s a JavaScript AST?

    View Slide

  11. 11
    ESTree
    de facto standard
    Parser
    Acorn
    Esprima
    Babylon: used by Babel, Acorn based
    Espree: used by ESLint, Acorn based
    What’s a JavaScript AST?

    View Slide

  12. 12
    AST Flow
    Source Code AST New AST
    New
    Source Code
    parser traverser generator

    View Slide

  13. 13
    Useful Tool
    AST Explorer

    View Slide

  14. 14
    Let’s create a babel plugin

    View Slide

  15. 15
    Create a babel plugin
    transform function take care the parser, traverser and generator.
    $ npm i -S @babel/core
    const { transform } = require("babel-core");
    index.js

    View Slide

  16. 16
    Replace var with const

    View Slide

  17. 17
    Create a babel plugin
    index.js
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'

    View Slide

  18. 18
    That’s all

    View Slide

  19. 19
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'
    Create babel plugin
    index.js
    Original source code
    Generated source code

    View Slide

  20. 20
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'
    Create babel plugin
    index.js
    Call transform function with src and defined plugin

    View Slide

  21. 21
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'
    Create babel plugin
    index.js
    Kind of visitor pattern

    View Slide

  22. 22
    Create babel plugin
    index.js
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'
    Kind of visitor pattern
    This function will be fired when
    this label is found in the AST

    View Slide

  23. 23
    Understand, but how to write it?

    View Slide

  24. 24
    Useful Tools
    AST Explorer

    View Slide

  25. 25
    Create babel plugin

    View Slide

  26. 26
    Create babel plugin
    var foo = 'foooooo'

    View Slide

  27. 27
    Create babel plugin
    var foo = 'foooooo'

    View Slide

  28. 28
    Create babel plugin
    index.js
    const { transform } = require("babel-core");
    const src = "var foo = 'foooooo'"
    const plugin = ({ types }) => ({
    visitor: {
    VariableDeclaration: nodePath => {
    if (nodePath.node.kind === "var") {
    nodePath.node.kind = "const";
    }
    }
    }
    });
    const { code } = transform(src, { plugins: [plugin] });
    console.log(code); // -> const foo = 'foooooo'

    View Slide

  29. 29
    If you have any question or feedback,
    please get in touch with twitter (@sottar_)
    Thank you~

    View Slide

  30. 30
    AST Explorer https://astexplorer.net/
    Acorn https://github.com/acornjs/acorn
    Esprima https://github.com/jquery/esprima
    Babylon https://github.com/babel/babel/tree/master/packages/babel-parser
    Espree https://github.com/eslint/espree
    Appendix

    View Slide