Re: [whatwg/dom] Make it possible to observe connected-ness of a node (#533)

dead-claudia left a comment (whatwg/dom#533)

> Why would we need a separate observer for connectedness? It seems to fit right in the scope of `MutationObserver`. 

Simply doing `.observe(document.documentElement, {childList: true, subtree: true})` and similar for shadow roots is sufficient for detecting connectedness changes. And that paired with a weak map would even let you put together your own unsubscribe mechanism.

This code implements liveness observers for all but children of declarative shadow roots:

```js
let observeShadow
const observers = new Set()
const registry = new FinalizationRegistry(held => {
    observers.delete(held)
})
const oldAttachShadow = Element.prototype.attachShadow
Object.defineProperty(Element.prototype, "attachShadow", {
    value() {
        const root = oldAttachShadow.apply(this, arguments)
        for (const weak of observers) {
            const observer = weak.get()
            if (observer) observeShadow(observer, root)
        }
        return root
    },
})

class LivenessObserver {
    #callback
    #observed = new WeakSet()
    #observer = new MutationObserver(records => {
        this.#check(records)
    })

    static {
        observeShadow = (observer, root) => {
            observer.#observer.observe(root, {
                childList: true,
                subtree: true,
            })
        }
    }

    constructor(callback) {
        this.#callback = callback
        observeShadow(this.#observer, document.documentElement)
        const weak = new WeakRef(this)
        observers.add(weak)
        registry.register(this, weak)
    }

    #check(records) {
        for (const r of records) {
            for (const n of r.removedNodes) {
                if (!this.#observed.has(n)) continue
                try {
                    this.#callback.removed?.(n)
                } catch (e) {
                    reportError(e)
                }
            }

            for (const n of r.addedNodes) {
                if (!this.#observed.has(n)) continue
                try {
                    this.#callback.added?.(n)
                } catch (e) {
                    reportError(e)
                }
            }
        }
    }

    observe(node) {
        this.#observed.add(node)
    }

    disconnect() {
        this.#observed.clear()
    }
}
```

Will note that this is probably not as fast as it could be.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/533#issuecomment-2839983366
You are receiving this because you are subscribed to this thread.

Message ID: <whatwg/dom/issues/533/2839983366@github.com>

Received on Tuesday, 29 April 2025 19:22:11 UTC