- From: Jeff Hykin <notifications@github.com>
- Date: Sat, 08 Jan 2022 17:05:42 -0800
- To: WICG/webcomponents <webcomponents@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <WICG/webcomponents/issues/951@github.com>
### 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