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

JavaScript Transformation - React Europe 2015

sebmck
July 06, 2015

JavaScript Transformation - React Europe 2015

sebmck

July 06, 2015
Tweet

More Decks by sebmck

Other Decks in Technology

Transcript

  1. { 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" } }] }] } }] }] } Data structure
  2. List • Program • VariableDeclaration • VariableDeclarator • Identifier •

    FunctionExpression • Identifier • BlockStatement • ReturnStatement • Identifier
  3. Parser Turns code into an AST Transformer Manipulates AST Generator

    Turns AST back into code Parser Turns code into an AST Transformer and Generator Traverses AST and manipulates it via strings jstransform Parser Turns code into an AST
  4. Lexical Analysis Turn code into a stream of tokens Syntactic

    Analysis Turn tokens into a tree Parser Turns code into an AST
  5. foo = 1 + “bar”; What is a token? Identifier

    Punctuator Number String 1. Identifier<foo> 2. Punctuator<=> 3. Number<1> 4. Punctuator<+> 5. String<bar> 6. Puncutator<;>
  6. class Foo extends Bar {} pp.parseClassDeclaration = function () {

    let node = this.startNode(); this.expect(tt._class); node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; Identifier Punctuator Keyword 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  7. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  8. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  9. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  10. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  11. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  12. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  13. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  14. pp.parseClassDeclaration = function () { let node = this.startNode(); this.expect(tt._class);

    node.id = this.parseIdentifier(); if (this.type === tt._extends) { this.next(); node.superClass = this.parseExprSubscripts(); }; node.body = this.parseClassBody(); return this.finishNode(node, "ClassDeclaration"); }; 1. Keyword<class> 2. Identifier<Foo> 3. Keyword<extends> 4. Identifier<Bar> 5. Punctuator<{> 6. Punctuator<}> Syntactic analysis
  15. { type: "ClassDeclaration", start: 0, end: 23, id: { type:

    “Identifier", start: 6, end: 9, name: “Foo" }, superClass: { type: “Identifier", end: 21, start: 18, name: “Bar" }, body: { type: “ClassBody", start: 21, end: 23, body: [] } } Syntactic analysis
  16. Visitor • Controls traversal state • Interface for visiting, replacing

    and removing nodes • Consolidates visiting logic
  17. var foo = bar + “”; Type inference Variable Declaration

    Program Variable Declarator Identifier Binary Expression Literal Identifier
  18. Transpilation var [x, y] = [1, 2]; var _ref =

    [1, 2]; var x = _ref[0]; var y = _ref[1];
  19. Identifier Function Expression Block Statement Return Statement Identifier Unidirectional tree

    Variable Declaration Program Variable Declarator Identifier Identifier
  20. Identifier Variable Declaration Program Variable Declarator Identifier Function Expression Block

    Statement Return Statement Identifier argument body[0] Root declarations [0] id init body body[0] id Bidirectional tree
  21. Path • Abstraction for dealing with node relationships • Constant,

    same-instance always • Reactive to tree changes - propagates updates
  22. Style Inference Retain input style in output Code Generation Turn

    the tree into code Generator Turns AST back into code
  23. Transformer Manipulates AST Generator Turns AST back into code Parser

    Turns code into an AST Lexical Analysis Turn code into tokens Syntactic Analysis Turn tokens into a tree Traversal Visit the tree Static Analysis Infer what nodes represent Code Generation Turn the tree into code Style Inference Retain input style in output
  24. var _ref = React.createElement("div", { className: “foo" }); function render()

    { return _ref; } React 0.14 Constant hoisting function render() { return React.createElement("div", { className: “foo" }); } React <= 0.13
  25. Inline elements ({ type: "div", props: { className: "foo", children:

    [ bar, { type: Baz, props: {}, key: "baz", ref: null } ] }, key: null, ref: null })
  26. class Counter extends React.Component { static propTypes = { initialCount:

    React.PropTypes.number }; static defaultProps = { initialCount: 0 }; state = { count: this.props.initialCount }; } Class properties
  27. function autobind(target, key, descriptor) { return { get: function ()

    { return descriptor.value.bind(this); } }; } class Person { @autobind getFullName() { return `${this.firstName} ${this.lastName}`; } } Decorators
  28. class Counter extends React.Component { tick() { this.setState({ count: this.state.count

    + 1 }); } render() { return <div onClick={::this.tick}> Clicks: {this.state.count} </div>; } } Bind syntax