[WICG/webcomponents] Observable Properties (Issue #951)

### TDLR: I don't think there is a way to watch all properties 

<br>

### Workaround #1 

- Use attributes instead of properties
- Use mutation observer to watch all attributes

#### Downside: extremely slow, and dom updates are unnecessary

<br>

### Workaround #2

- Use a proxy
- Trick the browser into thinking the proxy object is a Node

#### Downside: doesn't work 

Example:
```js
const proxySymbol = Symbol.for('Proxy')
const thisProxySymbol = Symbol('customObject')

// monkey patching instanceof:
const originalHasInstance = CustomComponent.prototype[Symbol.hasInstance]
CustomComponent.prototype[Symbol.hasInstance] = (item, ...args)=>(item instanceof Object && item[thisProxySymbol])||originalHasInstance(item, ...args)

const element = new CustomComponent({onConnect, onDisconnect, onAdopted, children})

const elementProxy = new Proxy(element, {
    defineProperty: Reflect.defineProperty,
    getPrototypeOf: Reflect.getPrototypeOf,
    ownKeys(original) { return Object.keys(original) },
    get(original, key) {
        console.debug(`getting key:`,key)
        if (key == proxySymbol||key == thisProxySymbol) {return true}
        if (key == elementSymbol) {return original}
        return original[key]
    },
    set(original, key, value) {
        if (key == proxySymbol||key == thisProxySymbol) {return}
        return original[key] = value
    },
})

//
// attempt
//
elementProxy instanceof Node;       // >>> true 
document.body.append(elementProxy)  // >>> caught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'
```

<br>

### Workaround #3

- Create a two-way link between the proxy and the element using symbols
- Monkey patch all these (and I'm probably missing a few) on HTMLElement, HTMLCollection, etc
  - children
  - append
  - getElementById
  - prepend
  - querySelector
  - querySelectorAll
  - replaceChildren
  - hasChildNodes
  - insertBefore
  - removeChild
  - replaceChild
  - childNodes
  - firstChild
  - lastChild
  - appendChild
  - contains
  - activeElement
  - pointerLockElement
  - fullscreenElement
  - elementFromPoint
  - elementsFromPoint
  - getSelection
  - firstElementChild
  - lastElementChild
  - getRootNode
  - isEqualNode
  - isSameNode

####  Downside: (other than the extreme monkey patching itself) this would still fail for things like the debugging value of `$0` that many browsers have when inspecting an element. It would return the non-proxy-wrapped element

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

Message ID: <WICG/webcomponents/issues/951@github.com>

Received on Sunday, 9 January 2022 01:05:55 UTC