Skip to content

Observable Properties #951

@jeff-hykin

Description

@jeff-hykin

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


Workaround #1

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

Downsides

  • extremely slow
  • dom updates often are unnecessary

Workaround #2

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

Downsides

  • doesn't work

Example:

const proxySymbol = Symbol.for('Proxy')
const thisProxySymbol = Symbol('customObject')


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'

Workaround #3

  • Create a two-way link between the proxy and the element using symbols
  • Monkey patch all these (and more) on Node, Element, HTMLElement, Document, 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

Downsides

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions