WebReflection / hyperHTML-Element

An extensible class to define hyperHTML based Custom Elements.
ISC License
202 stars 25 forks source link

Fix created() {} behavior cross browser. #23

Closed WebReflection closed 6 years ago

WebReflection commented 6 years ago

The current created() {...} method should grant somehow that a Custom Element is live and/or well known.

Unfortunately this is inconsistent due bugs present in 2 browsers out of 3 implementing Custom Elements.

Apparently the correct behavior is the one that would see created() invoke fail if the custom element is defined before DOMContentLoaded happens.

https://bugs.chromium.org/p/chromium/issues/detail?id=821831


Workaround

The proposed work around comes from this @cramforce tweet and it seems to work in general but it has the following outstanding issue: in a case where the custom element is the last child of a tree of single/last child it fails to ever return true if the parent node has no white spaces or extra nodes.

This is particularly easy to reproduce via hyperHTML template literals so that such work around might result into a never ready component.

<!doctype html>
<script>
this.onload = function () {
  // define custom-app with the ready work around
  hyper(document.body)`<custom-app say="hello world" />`;
  console.log(document.body.firstChild.ready); // false
};
</script>

In above example document.body as well as document.documentElement and document itself will not have a nextSibling so the result of a main custom element as body app would be "never ready".

Possible improvements

The not fully ready case never really happens with hyperHTML itself and it might occur for custom elements only when defined before DOMContentLoaded with Custom Elements within the body.

This is a specific issue with HyperHTMLElement class only, and very specific to the current document parsing state.

In order to be sure everything works:

In latter case this .ready getter would be redundant / pointless, since any CE could define this.ready = true in their created constructor.

cramforce commented 6 years ago

AMP short circuits the loop if document.readyState == 'complete' and if the loop determines that there is no nextSibling it does these 2 things

This could probably also be implemented with MutationObserver but the polling works pretty well.

coveralls commented 6 years ago

Coverage Status

Coverage remained the same at 100.0% when pulling 2ccdeafb8801b29470614bee86d7e16173b89582 on ready into 7386ddf0a7d1710684a0b376c6a9eb33033a1072 on master.

WebReflection commented 6 years ago

Thanks @cramforce . My current resolution with full code coverage uses indeed a similar approach.

It's not optimal when a node isn't "ready" for long time but it grants the following:

There's also a guard against fake DOMContentLoaded events so every bloody case should be covered.

Thanks for hints and info.