Re: [w3c/webcomponents] HTMLElement.prototype needs to define the custom element callbacks. (#582)

> E.g. should HTMLTemplateElement.prototype.adoptedCallback perform the adopting steps for template? Is that really something we want to expose to user code arbitrarily?

I would say the answer to the first is 'no' and the second is 'yes', but I'm not an implementor so I don't know what the implications of the second would really be.

I think the key distinction here is that these callbacks aren't overriding or otherwise triggering the internal procedure; rather, they're being called *by* those internal procedures [see below]. Calling `attributeChangedCallback` on any Element (custom, and I'm arguing also non-custom here) isn't what causes that element's attribute to change, that's what Element's `setAttribute` does. The behavior for a native element's response to `setAttribute` occurs in its definition of `setAttribute` before reaching Element's `setAttribute` and the custom elements spec implies to me that Element's `setAttribute` internally calls `this.attributeChangedCallback` at the very end. With this in mind, I think claiming that these should be no-ops is pretty straight-forward.

After writing this, I now realize that since `setAttribute` is defined on Element.prototype, `attributeChangedCallback` should actually exist there and Node.prototype would be more appropriate for `connectedCallback`, `disconnectedCallback`, and `adoptedCallback` since those are in response to changes to properties of Node.

----

Green field rambling ahead...

Ideally, you *would* be overriding these since the custom elements abstraction is really just allowing you to extend HTMLElement. All the usual caveats that come with extension in any language apply just as equally - not calling overridden behavior causes important things not to happen - but, in this scenario, all of these callbacks would be redundant:

- `attributesChangedCallback` would instead be handled by overriding `setAttribute` and the system should call that when setting attributes on a non-native extension of Element rather than changing internal state and calling the callback afterwards. You would need to call down to HTMLElement to get the native behavior to trigger of course (for example, being able to call `getAttribute` and actually get the previously set value).
- `adoptedCallback` would be handled by adding a setter for `ownerDocument`, the setter for `ownerDocument` on Node.prototype should then set `ownerDocument` on all its child nodes.
- `connectedCallback` and `disconnectedCallback` would be handled by adding a setter for `parentNode` during which, if both the new `parentNode` and `ownerDocument` were non-null, you would know if the element is being connected or disconnected. Or, after calling through Node's `parentNode` setter, you could just check `isConnected`.

But, again, I'm not an implementor so I don't know how well situated the internals of any of the browsers DOM implementations are to allow these types of changes so that extensions to HTMLElement (or any other base class for that matter) could act as true extensions to DOM objects.

In lieu of making natively defined DOM procedures call into their respective methods on non-native extensions, I think it would make sense to cause `customElements.define` to throw if you override any of the currently defined API of HTMLElement or below. That way, when the internals *are* ready to allow accessing a non-native method or property during the native implementation, you could remove that particular method or property from the blacklist without having to worry about breaking existing code. I'll open another bug on this.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/582#issuecomment-252351996

Received on Friday, 7 October 2016 20:23:40 UTC