Ember, sigh, why do you hate me?



  • Continuing the discussion from Status: Having my git changed to hg:

    @cartman82 said:

    STATUS: Making an ember widget.

    Code it in an html playground fiddle. Works great.

    Plug it into the app. Suddenly, it starts crashing.

    Uncaught TypeError: Cannot read property 'insertBefore' of null

    (from like 20 calls deep into some obscure Ember internals)

    Try it back in the fiddle. Works.Massage the fiddle to resemble my app code. Works.Remove all the superfluous crap from the app code. Crashes.Copy app code into the fiddle. Works.Extract the generate vendor.js from my grunt output and use it in the fiddle. Works.Virtually the same code in app, everything laid bare, just the widget on screen. Crashes.

    I want to die.

    This just turned good enough for its own thread.

    Finally isolated the fucker. See if you can spot it:

    {{#each items as |item index|}}<div class="drag-item">{{yield item}}</div>{{/each}}
    

    ===> Works

    {{#each items as |item index|}}
      <div class="drag-item">{{yield item}}</div>
    {{/each}}
    

    ===> Works

    {{#each items as |item index|}}
      <div class="drag-item">{{yield item}}</div>{{/each}}
    

    ===> CRASH #@#!#!

    Pro-tip: If you use Ember, never ever mess with the DOM directly (that's what I'm trying to do). You're gonna have a bad time.



  • Wait, isn't that used in Discourse? You're touching a component of Discourse?



  • @Magus said:

    Wait, isn't that used in Discourse? You're touching a component of Discourse?

    Oh shit you're right! EWWW!! GET IT OFF! GET IT OFF!!!


  • ♿ (Parody)

    @cartman82 said:

    See if you can spot it:

    Either it all needs to be on one line, or the "open" and "close" eaches need to be on their own lines?



  • @boomzilla said:

    Either it all needs to be on one line, or the "open" and "close" eaches need to be on their own lines?

    Something like that. It's the whitespaces, which turn into DOM "text" elements. The code works when both sides are buffered by text nodes, or when neither is. If one has some white space, but other doesn't, it goes into some strange code path while trying to clear the DOM and crashes.

    It doesn't help that both my test code and real code are exactly the same, with the same whitespace layout. Except, my app code is processed through grunt, while the test fiddle is compiled live. I guess there's some subtle difference in template compilers, because the grunt one somehow gets trimmed on one side and loses its "text node buffer", which reveals the bug.

    Mighty difficult to spot. It'll be even harder to actually fix.


  • ♿ (Parody)

    The one that crashes makes me angry. I have a cow-orker who thinks stuff like:

    <span><div><button>...</div>
        </span>
    

    ...is well formatted. There's no rhyme or reason. Well, there is. She just keeps running on until she gets so far out on the line, then puts in a line break.

    This is xhtml, so there's no problem with white space from the parser. I hate her so much.



  • Just enforce auto format before checkin?


  • ♿ (Parody)

    I should clarify, this is just a minor thing in her list of awfulness. Also, this sort of crap warns me that I've ventured into something she's touched, so it serves a purpose.



  • @boomzilla said:

    This is xhtml, so there's no problem with white space from the parser. I hate her so much.

    You think there isn't. But DOM actually gets an extra text node, which can matter in some circumstances. For example, using :first-child css selector, trying to inline DOM elements without gaps, etc. Internet explorer is ironically a useful tool there, because its dev tools show all empty text nodes that chrome and FF hide.


  • FoxDev

    @boomzilla said:

    Also, this sort of crap warns me that I've ventured into something she's touched, so it serves a purpose.

    Surely the commit log would also show that? 🚎


  • ♿ (Parody)

    @cartman82 said:

    You think there isn't.

    Pretty sure. This is all enterprise-java-land stuff. It goes through several stages before the browser gets it.


  • ♿ (Parody)

    @RaceProUK said:

    Surely the commit log would also show that?

    Yes, but I mean, as soon as I look at a file, I can just tell.



  • He'll catch the discourse-cooties!



  • @cartman82 said:

    But DOM actually gets an extra text node, which can matter in some circumstances. For example, using :first-child css selector

    The firstChild property selects the first child node. The :first-child pseudo-selector filters to elements that are the first child element. Text nodes are nodes, but not elements...



  • @Ragnax said:

    The firstChild property selects the first child node. The :first-child pseudo-selector filters to elements that are the first child element. Text nodes are nodes, but not elements...

    Right, I felt I was off, but was too lazy to look up. Either way, there are subtle gotchas if you disregard text nodes.



  • Something like that. It's the whitespaces, which turn into DOM "text" elements. The code works when both sides are buffered by text nodes, or when neither is. If one has some white space, but other doesn't, it goes into some strange code path while trying to clear the DOM and crashes.

    This isn't just an ember issue. It's pretty common in HTML templating languages because of:

    1. vague areas in the HTML spec that are left up to interpretation
    2. Strict adherence to XML/XHTML at some point during the rendering to HTML and a parser trying to be "smart" about perceived malformed source templates
    3. Regex parsing of the templates to create the document structure before rendering to HTML
    4. DOM DOM DOM DOM wonderful DOM DOM DOM

    I've seen the exact same thing show up in Java projects using JSTL/JSP


  • Banned

    DOM DOM DOOOOOOOOOM


  • BINNED

    I just recently had mustache.js choke on on something similar. Well, I'm guessing it was similar. It kept spewing garbage about unclosed sections and tags. Solved it by splitting up partials differently. Stupid solution, but hey, it worked.

    And I'm sure that my template was fine since both a mustache linter I found and the PHP parser had no problems with it.

    Then again, I'm pretty sure it was choking on something in bare string form, before it got inserted into DOM. I'm tempted to try and repro it now. Sadly, nothing to revert to, I never commited the broken version...


Log in to reply