Cache forwarded states to avoid duplication
This commit is contained in:
parent
e38d556531
commit
e80801b639
1 changed files with 35 additions and 1 deletions
36
state.js
36
state.js
|
@ -38,6 +38,7 @@ export class State extends EventTarget {
|
||||||
#target
|
#target
|
||||||
#options
|
#options
|
||||||
#queue
|
#queue
|
||||||
|
#forwardCache
|
||||||
|
|
||||||
constructor(target={}, options={}) {
|
constructor(target={}, options={}) {
|
||||||
super()
|
super()
|
||||||
|
@ -86,7 +87,17 @@ export class State extends EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
forward(property="value", fallback) {
|
forward(property="value", fallback) {
|
||||||
return new ForwardState(this, property, fallback)
|
if (!this.#forwardCache) this.#forwardCache = new Map()
|
||||||
|
const cached = this.#forwardCache.get(property).deref()
|
||||||
|
if (cached) {
|
||||||
|
return cached
|
||||||
|
} else {
|
||||||
|
const forwarded = new ForwardState(this, property, fallback)
|
||||||
|
ref = new Weakref(forwarded)
|
||||||
|
this.#forwardCache.set(property, ref)
|
||||||
|
forwardFinalizationRegistry.register(forwarded, [this.#forwardCache, property])
|
||||||
|
return forwarded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set(prop, value) {
|
set(prop, value) {
|
||||||
|
@ -98,6 +109,10 @@ export class State extends EventTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const forwardFinalizationRegistry = new FinalizationRegistry(([cache, name]) => {
|
||||||
|
cache.remove(name)
|
||||||
|
})
|
||||||
|
|
||||||
export class ForwardState extends EventTarget {
|
export class ForwardState extends EventTarget {
|
||||||
#backend
|
#backend
|
||||||
#property
|
#property
|
||||||
|
@ -186,4 +201,23 @@ export class StoredState extends State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const attributeObserver = new MutationObserver(mutations => {
|
||||||
|
for (const {type, target, attributeName: name} of mutations) {
|
||||||
|
if (type == "attributes")
|
||||||
|
target.state.proxy[name] = target.getAttribute(name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const component = (generator, name) => {
|
||||||
|
name = name ?? generator.name.replace(/([a-z])([A-Z])/g, (_, a, b) => `${a}-${b.toLowerCase()}`)
|
||||||
|
customElements.define(name, class extends HTMLElement{
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.state = new State(Object.fromEntries([...this.attributes].map(attribute => [attribute.name, attribute.value])))
|
||||||
|
attributeObserver.observe(this, {attributes: true})
|
||||||
|
this.replaceChildren(generator(this.state))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default State
|
export default State
|
||||||
|
|
Loading…
Reference in a new issue