ungap/custom-elements

Mutation observer takes time to process DOM insertions

Closed this issue · 2 comments

I have run into an interesting problem when using this polyfill in WebKit (= Safari). When I instantiate a custom built-in element and insert it into the DOM tree programmatically, like this...

const myElement=document.createElement("div", {is: "my-element"});
document.querySelector("body").appendChild(myElement);

...it takes a few milliseconds before the polyfill’s mutation observer processes the insertion asynchronously. This means that if I try to access the element’s custom properties or methods immediately after insertion I get an error because the property/method doesn’t exist yet. Like in this code:

const myElement=document.createElement("div", {is: "my-element"});
document.querySelector("body").appendChild(myElement);
myElement.someMethod();

...where the last line throws up an error (someMethod doesn’t exist) in WebKit but works fine in other browsers (because they’re not using the polyfill).

The only workaround I have been able to find is simply to wait one second after each insertion:

const myElement=document.createElement("div", {is: "my-element"});
document.querySelector("body").appendChild(myElement);
document.setTimeout(()=>{
  myElement.someMethod();    
}, 1000);

Is there a better way? As far as I know there is no way I can wait until all mutations have been processed, is there?

Or, would it be an option to add a feature that would allow me to tell the polyfill when I have inserted one of more elements and ask it to process them synchronously before I continue?

Is there a better way?

const MyElement = customElements.get('my-element');
const myElement = document.body.appendChild(new MyElement);
myElement.someMethod();

custom elements are defined lazily regardless of this polyfill ... if you create a custom elements with an is attribute and that element hasn't been defined yet, you'll have the exact same issue even with Chromium or Firefox, with native builtin support.

The same applies for non builtin elements ... if you create <my-element> and that's not defined yet, you'll have the exact same issue ... custom elements exists when the definition exists ... for that you have whenDefined('my-element') and that should trigger always after the MutationObserver had a chance to run so ... pick your poison, but if it's programmatically that you want to create custom elements, then use the class, not document.createElement indirection.