Prinzhorn / scrollmeister

Open-source JavaScript framework to declaratively build scrolling experiences
https://www.scrollmeister.com/
MIT License
37 stars 5 forks source link

Race condition / timing issue with custom behaviors #2

Closed Prinzhorn closed 6 years ago

Prinzhorn commented 6 years ago

See also #1, the same applies to custom conditions.

Currently we call Scrollmeister.defineBehavior before customElements.define. This is mandatory because when defining a custom element it will immediately call the static observedAttributes getter once. This implies that we need to know about all behaviors before the element is defined, inside the <head>. If a user includes the scrollmeister.js and then calls defineBehavior it will not work, as the attribute will not be observed. The CustomElementRegistry does not offer a way to redefine or remove a registered element, or else we could do that once a new behavior is added.

I see two solutions. Either we force the user to define behaviors before including the scrollmeister.js script (using some global config object) or we schedule the customElements.define call using raf. The first option is asking for tons of trouble/issues/stackoverflow posts because it is error prone (does it? defining new behavior/conditions is expert stuff that normal users don't need at all. But still, it feels weird to include them in this order). The second solution might have other implications. The browser will first treat the custom element as unknown and then upgrade them a tick later. Need to experiment with this.

Prinzhorn commented 6 years ago

Correction: since the elements follow the naming convention for custom elements (a dash) they do not inherit from HTMLUnknownElement. They will be unresolved and not unknown. So the second solution might just work. Assuming that https://github.com/WebReflection/document-register-element does the right things 😅

Prinzhorn commented 6 years ago

Seems to work, wrapped the customElements.define in an raf

Prinzhorn commented 6 years ago

BTW this was needed to separate the "extras" build, which (as of now) simply bundles more behaviors and imports them after the core (which calls customElements.define, now async)