Babel - Facebook April 2015

9b7cbca4917f83679696b0924d0ed09d?s=47 sebmck
April 17, 2015
2.4k

Babel - Facebook April 2015

9b7cbca4917f83679696b0924d0ed09d?s=128

sebmck

April 17, 2015
Tweet

Transcript

  1. None
  2. What is it? • An ES6 and beyond JavaScript compiler

    • A JSX optimising compiler • A transformation platform for JavaScript
  3. Terminology • AST - A tree representation of source code.

    • Scope - A “boundary” that things can be bound to. • Traversal - The act of recursively visiting a root node and its children. • Traversal path - Representation of a child-parent relationship. • Transformer - Isolated transformation module with a specific goal. • Visitor - Controls a traversal.
  4. Architecture

  5. Architecture Parser Turns code into an AST Transformer Manipulates AST

    Generator Turns AST back into code
  6. Parser

  7. Parser • Recursive descent parser • Separate functions defined for

    all syntactic elements that are recursively called • Based on Acorn (https://github.com/marijnh/acorn)
  8. Plugins • Modular • Each major syntax extension is separated

    into extensions • Supports: • ES6+ • Flow • JSX
  9. AST var foo = function foo() { return bar; };

  10. AST { type: "Program", body: [{ type: "VariableDeclaration" kind: "var",

    declarations: [{ type: "VariableDeclarator", id: { type: "Identifier", name: "foo" }, init: { type: “FunctionExpression", id: { type: “Identifier”, name: “foo” }, params: [], body: [{ type: "BlockStatement", body: [{ type: "ReturnStatement", argument: { type: "Identifier", name: "bar" } }] }] } }] }] }
  11. AST Variable Declaration Program Variable Declarator Identifier Function Expression Block

    Statement Return Statement Identifier
  12. ESTree • Collaborative AST spec from all the major consumers

    • Contextless definitions
  13. Transformation

  14. Visitors • Describes what nodes to visit. • Abstracts traversal

    logic from visiting logic. • Controls the traversal state - whether to stop or skip specific node trees. • Allows efficient reuse of common visitor logic.
  15. Traversal • Handles visiting each node and branch in the

    tree. • Handles replacing nodes: • Expressions to statements etc. • Manages scope: • Tracks bindings and references.
  16. Traversal paths • Node relationships are abstracted into paths. •

    Paths are retained between traversals. • Very powerful as path is constant, can store metadata. • A path always resolves to the same node. • Even after replacement and relocation.
  17. Transformers • Each feature is split into a separate transformer.

    • Modular, easily toggle-able. • Good abstraction for grouping common logic. • Independent traversal for each transformer. • Easier to maintain state.
  18. Demo

  19. Future optimisations

  20. Transformer traversal optimisation • Entire traversal for each transformer is

    inefficient. • Prepass the AST and check what branches each transformer actually needs. • Flexibility of having a stateful visitor without having to visit all nodes.
  21. Transformer traversal optimisation function check(node) { return t.isProperty(node) && node.computed;

    }
  22. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  23. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  24. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  25. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  26. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  27. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  28. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  29. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  30. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  31. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  32. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  33. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  34. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  35. Transformer traversal optimisation function createNode(type, props) { return { type:

    type, ["is" + type]: true, ...props }; }
  36. AST diffing • Incremental builds • Store previous original and

    transformed AST as well as some metadata (scope tracking etc) • Diff previous original AST and current untransformed AST • Transpose differences into previous transformed AST and transform only the specific bits
  37. Generation

  38. Retaining original newlines • When printing a node • Get

    node starting token • Get previous token • Compare newlines between tokens • Add newlines
  39. Generating generated node newlines • Is this a function declaration?

    If so, require a newline before and after. • Is it a directive? Require a newline after. • Is this an if statement with a block statement consequent? If so, insert a newline before and after.
  40. JSX optimisations

  41. Constant Value Types function render() { return <div className="foo" />;

    } var foo = <div className="foo" />; function render() { return foo; }
  42. Constant Value Types 1. Check if JSX element is immutable.

    2. Collect all references (Make sure references are “constant”. ie. never reassigned). 3. Walk up the scope tree, checking for the highest scope that contains all the references. 4. Create a declaration to save the JSX element and then insert it before the “scope block”.
  43. Inline React Elements <div className="foo">{bar}<Baz key="baz" /></div> ({ type: “div",

    props: { className: “foo", children: [ bar, { type: Baz, props: {}, key: "baz", ref: null } ] }, key: null, ref: null })
  44. Tooling

  45. Integrations • Atom • Broccoli • Browserify • Browser compiler

    • Brunch • Cogs • Connect • CLI • Ember CLI • ESLint • Duo • Gobble • Grunt • Gulp • Istanbul • Jade • Jest • Karma • Kraken devtools • Mimosa • Mocha • Nodemon • Meteor • Power assert • Rails/Sprockets • Require hook • Ruby • Sails • Sublime • Webpack
  46. Conclusion • Write a plugin: https://babeljs.io/docs/usage/ plugins • Contribute! https://github.com/babel/babel/blob/

    master/CONTRIBUTING.md • Questions?