Re: [WICG/webcomponents] Cleaning up (undefining) custom elements? (#754)

Can we re-open this issue?

In my humble opinion, any API without cleanup methods should always have its cleanup issue remain open, regardless of how long it takes to find a solution, because it is simply best practice to always have cleanup in mind when making _any_ API.

Having this issue closed discourages a good mindset that, in my opinion, every developer should have.

@rniwa:

> * What happens to existing elements' prototype & its methods.

Two ideas:

1. The element gets removed from DOM, and a new non-upgraded element gets placed in its spot, all synchronously. Any parent element (f.e. another custom element using MutationObserver) or API using the child should be responsible to clean up when the element is removed.
2. Downgrade; undo the prototype changes that upgrade did. But keep it simple: any own properties that were added would simply remain on the downgraded element.
   - Before downgrade, call the element's `disconnectedCallback` so it has a chance to clean up. Either that, or a new `downgradeCallback`, but perhaps that would be unnecessary. `disconnectedCallback` is effectively synonym for time to cleanup.

I think option 2 is a lot better. However I think an idea similar to [`childConnectedCallback`](https://github.com/WICG/webcomponents/issues/619) or [`childDisconnectedCallback`](https://github.com/WICG/webcomponents/issues/550) would be helpful for parent elements to clean certain things up. `customElement.whenUndefined(...)` could be helpful for this, though callbacks like `childUpgradedCallback` and `childDowngradedCallback` would be ergonomic and easy to use, leading to a better dev experience. Compare those callbacks with having to continually make calls to `cE.whenDefined`  and `cE.whenUndefined` to continually have new promises in order to react to repeated defines and undefines: it would be messier.

> * What happens when someone clones an existing element, which is now "undefined".

If we go with option 2 above, this is easier. They simply still have the same reference, and the referenced element may have cleaned itself up.

Going with option 1 would be more complicated, and it would lead to the same problems people had before web components and before mutation observer: how would the clean up when an element is removed (or downgraded)? `cE.whenUndefined` would be the tool to use in this case. But an option with better DX would be to allow people to observe downgrades by extending the DOM Mutation events to observe downgrade, and to also not deprecate that API but instead add a batching mechanism to it to prevent all the performance concerns that caused its deprecation. Those events are highly useful for developer experience when they need to observe a particular element from the outside, as compared to MutationObserver (MO is better for broad whole-tree observation, or adding new callbacks to CEs).

> * What happens when when a custom element reaction callback or upgrading a custom element (inadvertently) undefines itself before draining some of items in [custom element reaction queue](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reaction-queue).

If the element undefines itself (for whatever reason),

- two options for existing callbacks:
   1. cancel any attribute, adopted, or connected callback (remove them from queue or whatever),
   2. or just run them first before finally
- running disconnected callback (if it is already queued, just leave it).
- ensure downgrade happens right after disconnectedCallback

This would work the same (or with little difference) regardless of options 1 and 2 above. But still i think this makes more sense with option 2.

> I'm sure there is a lot more cases to consider that I haven't even thought about.

Got any more? The above _seems_ fairly straight forward: downgrading is just a simple object manipulation (in case we choose option 2, which seems better) just like upgrading is:

- in the upgrade case, prototypes are injected, constructor runs on the instance (yay JavaScript magic), and finally connectedCallback runs. Note that the upgraded element may have had existing own properties added to it before upgrade.
- in the downgrade case, disconnectedCallback runs, then prototypes are removed. Note that, reciprocally to upgrade, the downgraded instance may have remaining own props still present, which is totally fine. A future upgrade could re-use those again, for example, just as the very first upgrade that may encounter existing own props.

Wdyt?

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

Received on Monday, 8 March 2021 21:01:13 UTC