Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaScript ASTことはじめ /JavaScript AST

JavaScript ASTことはじめ /JavaScript AST

メドレー開発本部の社内勉強会「TechLunch」で、JavaScript ASTについて紹介させていただきました。

発表者:平木聡

Medley Inc.

June 22, 2018
Tweet

More Decks by Medley Inc.

Other Decks in Technology

Transcript

  1. JavaScript AST͜ͱ͸͡Ί

    View Slide

  2. Agenda
    • JavaScript ASTͱ͸Կ͔?
    • JavaScript ASTͷجૅ஌ࣝ
    • JavaScript AST࢖ͬͯԿ͔ͯ͠ΈΔ

    View Slide

  3. JavaScript ASTͱ͸Կ͔?

    View Slide

  4. ͦ΋ͦ΋ASTͱ͸
    ͦ΋ͦ΋AST͸ந৅ߏจ໦ͷӳޠ໊Ͱ͋Δabstract syntax treeͷུ
    শʹͳΓ·͢ɻίϯύΠϥͱ͔ΠϯλϓϦλͳͲͷݴޠॲཧܥͷ
    தؒॲཧʹྑ͘࢖ΘΕΔख๏Ͱ͢ɻ(ͳ͓؊ػೳͷ਺஋ʹ΋ಉ͡
    ASTͱ͍͏ུশ͕͋Δ໛༷)
    h"ps:/
    /en.wikipedia.org/wiki/Abstractsyntaxtree

    View Slide

  5. ͦ΋ͦ΋ASTͱ͸
    ΩϞͱͯ͠͸ॻ͔Ε͍ͯΔϓϩάϥϜΛߏจղੳͯ͠ߏ଄Խʹෆ
    ཁͳ෦෼͸࡟আͯ͠ɺ໦ߏ଄ͱͯ͠දݱ͍ͯ͠Δσʔλʹ͢Δͱ
    ͍͏ͱ͜ΖͰ͢ɻ

    View Slide

  6. ͦ΋ͦ΋ASTͱ͸
    ͜ͷASTࣗମ͸ಛʹJSݻ༗ͷ΋ͷͱ͍͏Θ͚Ͱ͸ͳ͘ɺ৭ʑͳݴ
    ޠͰ࢖ΘΕ͍ͯ·͢ɻྫ͑͹JavaͰ࢖ΘΕΔIDEͷEclipseͰ΋Java
    ͷߏจղੳʹ࢖ͬͯͨΓ͢ΔͬΆ͍Ͱ͢ɻ
    h"p:/
    /www.eclipse.org/ar1cles/Ar1cle-
    JavaCodeManipula1on_AST/index.html
    ͜ͷASTʹ͍ۙख๏Ͱ(ݫີʹ͸ҧ͏)ߏங͞Ε͍ͯΔͷ͕਎ۙͰ͍
    ͏ͱDOMͩͬͨΓ΋͠·͢ɻ

    View Slide

  7. JavaScript AST͸Ͳ͜Ͱ࢖ΘΕ͍ͯΔͷ͔?
    • React
    • Babel
    • UglifyJS
    • ESLint
    • PowerAssert
    ͳͲͳͲ

    View Slide

  8. JavaScript AST͸Ͳ͜Ͱ࢖ΘΕ͍ͯΔͷ͔?
    ҰྫͰ͕͢ݱࡏͷϑϩϯτΤϯυ։ൃʹ͸͔ܽͤͳ͍ϓϩμΫτ
    ͸େମ࢖ΘΕͯΔΜ͡Όͳ͍Ͱ͠ΐ͏͔ɻ
    มΘΓμωͱͯ͠ಠࣗʹJSͷϚΫϩΛ࡞ΕΔsweet-js/sweet-core
    ͳΜ͔Ͱ΋࢖ΘΕ͍ͯ·͢ɻ

    View Slide

  9. JavaScriptք۾ͰͷASTͷաڈ
    JSք۾ͰͷASTͷऔΓѻ͍ͳͲͷ࿩͸ผʹྺ࢙Λશ෦஌ͬͯΔΘ
    ͚͡Όͳ͍ΜͰ͕͢ɺ͔͍ͭ·ΉͱҎԼͷΑ͏ͳྲྀΕʹͳΔ͔
    ΋ɻ

    View Slide

  10. JavaScriptք۾ͰͷASTͷաڈ
    • FirefoxͰ࢖ΘΕ͍ͯͨSpiderMonkyͰ2010೥ʹParser API͕౥
    ࡌ͞Εͨ
    • Parser APIͷJSϙʔτͷzaach/reflect.js͕2011೥4݄͘Β͍ʹϦ
    Ϧʔε

    View Slide

  11. JavaScriptք۾ͰͷASTͷաڈ
    • JavaScript ASTͰຊ֨తʹ࢖ΘΕͩͨ͠jquery/esprima͕2011೥
    11݄͘Β͍ʹϦϦʔε
    • ݩʑ͸࡞ऀͷAriya͞ΜͷݸਓϓϩδΣΫτ͚ͩͬͨͲɺ3೥
    ͘Β͍લʹjQueryࡒஂʹҠ؅
    • esprima஗͍͗ͬͯͬͯ͢acornjs/acorn͕ొ৔

    View Slide

  12. JavaScriptք۾ͰͷASTͷաڈ
    • ࠷ॳ͸acorn࢖ͬͯͨBabel͕೿ੜͤͯࣗ͞લͰbabel/babylonΛ
    2012೥9݄͘Β͍͔Β࡞ͬͨΓ
    • ࢓༷֎ͷ͜ͱ΋Ͱ͖ΔΑ͏ʹ֦ு͞ΕͯΔ
    • JavaScript ASTΛ࡞ΔϥΠϒϥϦ͕৭ʑग़͖ͯͯޓ׵ੑ͕͋ͬͨ
    Γແ͔ͬͨΓͱ͍͏ঢ়گͩͬͨͷΛ2015೥ʹjQueryࡒஂ΍
    Mozilla΋ೖͬͯestree/estreeͱ͍͏JavaScript ASTͷඪ४ن͕֨
    Ͱ͖Δ

    View Slide

  13. JavaScriptք۾ͰͷASTͷաڈ
    ͜Μͳײ͡Ͱݱࡏ৭ʑͳϓϩμΫτͰ࢖ΘΕ͍ͯΔJavaScript AST
    ϥΠϒϥϦ͕৭ʑͰ͖͖ͯ·ͨ͠ɻ
    ༗໊ॴΛϐοΫΞοϓ͚ͨͩ͠ͳΜͰɺѥྲྀͷύʔα΋৭ʑ͋Γ
    ྫ͑͹ESLintͳΜ͔͸ݱࡏesprimaͱޓ׵ੑ͕͋Δeslint/espreeͱ
    ͍͏ύʔαΛࣗલͰ࡞ͬͯ࢖ͬͯͨΓ͠·͢ɻ

    View Slide

  14. JavaScript ASTͷجૅ஌ࣝ

    View Slide

  15. JavaScript AST͸࣮ࡍͲΜͳίʔυʹͳΔͷ͔
    JavaScript AST͸ιʔείʔυΛ໦ߏ଄ʹม׵ͯ͠ɺ࠷ऴతʹ
    JSONܗࣜʹͯ͠දݱ͍͖ͯ͠·͢ɻ
    ԼهͷΑ͏ͳ؆୯ͳJSίʔυΛྫʹऔΓ·͢ɻ
    var hello = 'Hello World';
    function sayHello() { console.log(hello) }

    View Slide

  16. JavaScript AST͸࣮ࡍͲΜͳίʔυʹͳΔͷ͔
    ࠓճ͸acornΛ࢖ͬͯASTʹม׵͢ΔͱԼهͷΑ͏ͳJSONܗ͕ࣜ
    Ͱ͖·͢ɻ
    {
    "type": "Program",
    "start": 0,
    "end": 69,
    "body": [
    {
    "type": "VariableDeclaration",
    "start": 0,
    "end": 26,
    "declarations": [
    {
    "type": "VariableDeclarator",
    "start": 4,
    "end": 25,
    "id": {
    "type": "Identifier",
    "start": 4,
    "end": 9,
    "name": "hello"
    },
    "init": {
    "type": "Literal",
    "start": 12,
    "end": 25,
    "value": "Hello World",
    "raw": "'Hello World'"
    }
    }
    ],
    "kind": "var"
    },
    {
    "type": "FunctionDeclaration",
    "start": 27,
    "end": 69,
    "id": {
    "type": "Identifier",
    "start": 36,
    "end": 44,
    "name": "sayHello"
    },
    "generator": false,
    "expression": false,
    "params": [],
    "body": {
    "type": "BlockStatement",
    "start": 47,
    "end": 69,
    "body": [
    {
    "type": "ExpressionStatement",
    "start": 49,
    "end": 67,
    "expression": {
    "type": "CallExpression",
    "start": 49,
    "end": 67,
    "callee": {
    "type": "MemberExpression",
    "start": 49,
    "end": 60,
    "object": {
    "type": "Identifier",
    "start": 49,
    "end": 56,
    "name": "console"
    },
    "property": {
    "type": "Identifier",
    "start": 57,
    "end": 60,
    "name": "log"
    },
    "computed": false
    },
    "arguments": [
    {
    "type": "Identifier",
    "start": 61,
    "end": 66,
    "name": "hello"
    }
    ]
    }
    }
    ]
    }
    }
    ],
    "sourceType": "module"
    }

    View Slide

  17. JavaScript AST͸࣮ࡍͲΜͳίʔυʹͳΔͷ͔
    શવಡΊͳ͍ͱࢥ͏ͷͰɺ෼͔Γ΍͍͢Α͏ͳπϦʔܗࣜͷεΫ
    γϣ͕ͪ͜Βɻ

    View Slide

  18. JavaScript ASTͷม׵ϧʔϧ
    ͲͷΑ͏ʹม׵͞ΕΔ͔?ͷϧʔϧ͸࢖͏ύʔαͷυΩϡϝϯτ
    ΍ɺParser API - Mozilla | MDNɺestree/estree: The ESTree Specͳ
    Μ͔Λࢀߟʹ͠·͢ɻ΋͏ͪΐ͍ಥͬ͜Μͩ࿩Ͱ͍͏ͱ
    ECMAScriptͷ࢓༷ॻ΋߹ΘͤͯಡΉͱΑ͍͔΋͠Εͳ͍Ͱ͢ɻ
    • h#ps:/
    /developer.mozilla.org/en-US/docs/Mozilla/Projects/
    SpiderMonkey/Parser_API
    • h#ps:/
    /github.com/estree/estree
    • h#ps:/
    /www.ecma-internaEonal.org/ecma-262/8.0/index.html

    View Slide

  19. ύʔαͰม׵͞Εͨ΋ͷͨͪͷઆ໌
    ͞Βͬͱࠓճͷ΋ͷΛୈೋ֊૚·Ͱઆ໌͢Δͱɺ͜Μͳײ͡Ͱ͢
    • Program
    • ϧʔτʹͳΔΦϒδΣΫτ
    • Կ͸ͳ͘ͱ΋ઈରʹม׵͢Δͱ࡞ΒΕΔ
    • ϓϩάϥϜ͸શ෦͜ͷ߲໨ͷbodyʹ໦ߏ଄Ͱ֨ೲ͞ΕΔ

    View Slide

  20. ύʔαͰม׵͞Εͨ΋ͷͨͪͷઆ໌
    • VariableDeclaration
    • var hello = 'Hello World';ͷ෦෼
    • ม਺એݴ͸͜ͷ߲໨ʹͳΔ
    • kind͕ม਺એݴͷΩʔϫʔυͷछྨʹͳΔɻ
    • declarations͕એݴ͞Ε͍ͯΔ಺༰Λ֨ೲ͍ͯ͠Δ෦෼
    • ม਺໊΍ॳظ஋ʹԿ͕ೖ͍ͬͯΔͳͲ͕֨ೲ

    View Slide

  21. ύʔαͰม׵͞Εͨ΋ͷͨͪͷઆ໌
    • FunctionDeclaration
    • function sayHello() { console.log(hello) }ͷ෦

    • ؔ਺એݴ͸͜ͷ߲໨ʹͳΔ
    • id͕ؔ਺໊ͳͲ֨ೲ͍ͯ͠Δ෦෼
    • params͸ࠓճۭ͕ͩɺԾҾ਺Λ֨ೲ͍ͯ͠Δ෦෼

    View Slide

  22. ݸੑ๛͔ͳύʔαͨͪ
    Ͳͷύʔαʔ΋جຊͱͯ͠͸͜ΕΒͷ߲໨͸ESTreeͰఆٛ͞Εͯ
    ͍Δ΋ͷΛ࢖͍ͬͯΔͷͰ͕͢ɺࡉ͔͍ҧ͍͕͋ͬͨΓɺ
    bablylonͷΑ͏ʹಠࣗͰ৭ʑͳ߲໨ΛೖΕ͍ͯͨΓ͢Δͱ͍͏ײ
    ͡ʹͳ͍͖ͬͯ·͢ɻ
    h"ps:/
    /github.com/babel/babylon/blob/master/ast/spec.md

    View Slide

  23. JavaScript ASTͷ࢖͍Ͳ͜Ζ
    ͜͜·Ͱجຊతͳ࿩Λ͖ͯ͠·͕ͨ͠ɺͰ͸JavaScript ASTΛࣗ෼
    ୡͰ࢖͏৔߹…Ͳ͏͍͏ͱ͖Ͱ͠ΐ͏͔?ͺͬͱࢥ͍ͭ͘ͱ͜Ζ͸
    ͜Μͳײ͔͡ͳ͋ͱɻ
    - babelͷϓϥάΠϯ࡞੒
    - eslintͷϓϥάΠϯ࡞੒
    - ࣗલͰιʔείʔυΛมߋ͢Δ(APIมߋͳΜ͔ͷ)πʔϧ࡞Δͱ͖

    View Slide

  24. JavaScript ASTͷ࢖͍Ͳ͜Ζ
    ݸਓతʹ͸ڊਓͷݞʹ৐͔ͬΓ͍ͨͷͰɺ༻్͕ϓϥάΠϯ࡞੒
    ʹͳͬͨΓͯ͠·͕͢ɺJavaScript ASTͷ࢓૊ΈΛ࢖͑͹ࣗલͷτ
    ϥϯεύΠϥΛ࡞ͬͨΓ΋Ͱ͖Δ͸ͣͰ͢ɻ
    ࣮ࡍʹJavaScript ASTΛ࢖ͬͯJSΛੜ੒͢Δʹ͸ɺ঺հͨ͠ύʔα
    ͷଞʹASTΛtraverseͯ͠ॲཧ͢ΔϥΠϒϥϦ(estraverseͳͲ)΍
    AST͔ΒJSΛੜ੒͢ΔϥΠϒϥϦ(escodegenͳͲ)͕ඞཁʹͳΓ·
    ͢ɻ

    View Slide

  25. JavaScript AST࢖ͬͯԿ͔ͯ͠ΈΔ

    View Slide

  26. AST Explore
    ࠷ޙʹͪΐͬͱ࣮ͨ͠ྫΛ͝঺հͯ͠ऴΘΓ·͕͢ɺͦͷલʹ
    JavaScript ASTΛѻ͏ͷʹແͯ͘͸ͳΒͳ͍πʔϧ͕͋ΔͷͰ঺
    հɻ

    View Slide

  27. AST Explore
    AST Explore: h.p:/
    /astexplorer.net/

    View Slide

  28. AST Explore
    ͜ͷαΠτ͸JavaScript AST͚ͩͰ͸ͳ͘ଞͷ৭ʑͳݴޠͷύʔα
    ΍ίʔυδΣωϨʔλ͕ΦϯϥΠϯͰ؆୯ʹͰ͖ΔΑ͏ʹͳͬͯ
    ͍ΔαΠτͰ͢ɻ
    JSBin΍JSFiddleͷAST൛ͱ͍͏ײ͡ɻSave͢ΔͱύʔϚϦϯΫ࡞
    ͬͯ͘ΕͨΓASTͷπϦʔ͕ݟ΍͔ͬͨ͢Γ͢ΔπʔϧͰ͢ɻ
    ࢖͍͍ͨύʔα΍δΣωϨʔλ΋৭ʑͳछྨ͔Βબ΂·͢ɻࠓճ
    ͷྫ΋͜ͷπʔϧ࢖ͬͯ঺հ͠·͢ɻ

    View Slide

  29. var Ͱॻ͔ΕͨJSΛconstʹॻ͖͔͑Δ
    ύʔα: babylon v7 / τϥϯεύΠϥ: babel7
    DEMO: varΩϥΠ

    View Slide

  30. Vue.js 1.xܥ͔Β2.xܥͷϚΠάϨʔγϣϯʹ଱͑Δ
    ύʔα: acorn / τϥϯεύΠϥ: jscodeshi/
    h"ps:/
    /vuejs.org/v2/guide/migra4on.html#a"ached-removed
    DEMO: a(atchͷϚΠάϨʔγϣϯ

    View Slide

  31. ऴΘΓ

    View Slide

  32. ࢀߟ
    • h#ps:/
    /speakerdeck.com/michaelficarra/spidermonkey-parser-
    api-a-standard-for-structured-js-representa;ons
    • h#p:/
    /azu.github.io/slide/JSojisan/#1
    • h#ps:/
    /efcl.info/2016/03/06/ast-first-step/
    • h#ps:/
    /efcl.info/2015/02/26/recent-js-ast/
    • h#ps:/
    /medium.com/@jotadeveloper/abstract-syntax-trees-on-
    javascript-534e33361fc7

    View Slide

  33. ࢀߟ
    • h#ps:/
    /www.sitepoint.com/understanding-asts-building-babel-
    plugin/
    • h#ps:/
    /github.com/jamiebuilds/babel-handbook
    • h#ps:/
    /github.com/facebook/jscodeshi<

    View Slide