glimmer-vm icon indicating copy to clipboard operation
glimmer-vm copied to clipboard

Human readible(-ish) wireformat compilation

Open chancancode opened this issue 5 years ago • 3 comments

Changes the output of precompile.

Before:

{"id":null,"meta":{},"block":"{\"symbols\":[],\"hasEval\":false,\"upvars\":[\"obj\"],\"statements\":[[10,\"input\"],[15,2,[34,0]],[12],[13]]}"}

After (DEBUG):

{
  id: null,
  meta: {},
  block: () => {
    /*

    Source:

    ```hbs
    <input value={{obj}} />
    ```

    Transformed:

    ```hbs
    <input value={{obj}} />
    ```

    */

    /* Wire Format */

    return {
      symbols: [],
      hasEval: false,
      upvars: [
        "obj"
      ],
      statements: [
        // ["open-element","input"]
          [10,"input"],
        // ["dynamic-attr","value",["get-free-in-append-single-id","obj"],null]
          [15,2,[34,0]],
        // ["flush-element"]
          [12],
        // ["close-element"]
          [13]
      ]
    }
  }
}

After (non-DEBUG):

{
  id: null,
  meta: {},
  block: () => {
    /*

    Source:

    ```hbs
    <input value={{obj}} />
    ```

    Transformed:

    ```hbs
    <input value={{obj}} />
    ```

    WireFormat:

    ```js
    {
      symbols: [],
      hasEval: false,
      upvars: [
        "obj"
      ],
      statements: [
        // ["open-element","input"]
          [10,"input"],
        // ["dynamic-attr","value",["get-free-in-append-single-id","obj"],null]
          [15,2,[34,0]],
        // ["flush-element"]
          [12],
        // ["close-element"]
          [13]
      ]
    }
    ```

    */

    return JSON.parse("{\"symbols\":[],\"hasEval\":false,\"upvars\":[\"obj\"],\"statements\":[[10,\"input\"],[15,2,[34,0]],[12],[13]]}");
  }
}

After (non-DEBUG, minified):

{id:null,meta:{},block:()=>JSON.parse("{\"symbols\":[],\"hasEval\":false,\"upvars\":[\"obj\"],\"statements\":[[10,\"input\"],[15,2,[34,0]],[12],[13]]}")}

Implications and considerations:

  • The output of precompile is no longer JSON.parse-able. However, this is needed for strict mode anyway, and the documentation has always recommended using new Function to parse the output.

  • Slightly inflated WF size in non-DEBUG + minified: each template now adds an additional 16 ASCII bytes, ()=>JSON.parse(${WF}) in the "blocks" field. I don't imagine this to be a big deal, as it should be pretty GZip-able? If it is a problem, we can pass in JSON.parse, so p=>p(${WF})?

  • Not sure how changing the "block" field from a string to a function would impact parse time. Would we still need the JSON.parse trick in non-DEBUG mode due to lazy parsing? Could we just leave the JS syntax as-is inside the function body, like what I did in the DEBUG version?

chancancode avatar May 03 '20 18:05 chancancode

IE 11 tests are failing because the precompile output uses arrow functions which is not supported. Should I switch it to use function() { ... }?

chancancode avatar May 03 '20 22:05 chancancode

Slightly inflated WF size in non-DEBUG + minified: each template now adds an additional 16 ASCII bytes, ()=>JSON.parse(${WF}) in the "blocks" field. I don't imagine this to be a big deal, as it should be pretty GZip-able? If it is a problem, we can pass in JSON.parse, so p=>p(${WF})?

Can we make the JSON.parse on the caller side (e.g. if a string is returned from calling .block() call JSON.parse)?

rwjblue avatar May 04 '20 16:05 rwjblue

IE 11 tests are failing because the precompile output uses arrow functions which is not supported. Should I switch it to use function() { ... }?

Yes

rwjblue avatar May 04 '20 16:05 rwjblue