skatejs/template-html

necessity of wrapping the element in order to dynamically project <content>

andyjcross opened this issue · 2 comments

I don't have much experience writing polyfills, so forgive me and disregard if this is a dumb question.

I was wondering why the usage of a wrapper element that mostly implements the DOM element interface is necessary, versus simply overriding the methods on the prototype of the custom element you're declaring? Similar to how mutation observers are polyfilled in skatejs for IE:

Object.defineProperty(elementPrototype, "innerHTML", {...

If I write a custom element called "my-component" that projects some content from the light DOM, I'm assuming as it is now I couldn't then nest it inside a parent component and set its content dynamically:

<my-component>{{content via data-binding}}</my-component>

because a templating engine or whatever I'm using doesn't know to create the wrapper. Whether it just resets .innerHTML or does something more efficient, it won't trigger the projection logic that might (or might not, depending on the new content) be necessary.

Thanks!

looks like this was addressed. cool.

Hey, sorry I never responded to this. I did see it but admittedly forgot to get back to you.

In short, yes, this is being rectified. The current implementation in master is changing and is considered unstable, though the tests pass. I'm currently exploring the best way to do this.

The long answer is that simply overriding prototypes doesn't seem to be a viable option. It would be the best option if Webkit didn't have this bug that prevents one from getting the native accessor implementations using getOwnPropertyDescriptor(). Even if that would be possible, Webkit has a bug where you're not allowed to override built-in property descriptors.

Due to these bugs, you have to re-implement, from scratch, the behaviour of things like innerHTML and manually keep track of childNodes, parentNode et al. Manually re-implementing innerHTML is possible using DOMParser, but that requires that you leave the HTMLBodyElement prototype untouched because internally the DOMParser implementation expects all native implementations to be intact in order for you to retrieve the parsed DOM content off the parser result. Basically, you have to modify all element constructors except for the body element.

This is all well and good until you realise that not all HTML elements have their own constructor and that some simply derive from HTMLElement directly. This means that in order to do everything through prototype overrides, one must be able to override HTMLElement.prototype. Due to the Webkit bugs, this simply isn't an option.

The solution, which I am elaborating on is using wrapper objects similar to the Polymer polyfill. Eventually we might be able to use a hybrid approach, but I anticipate that becoming very dirty, very quickly.