Cache forwarded states to avoid duplication

This commit is contained in:
Talia 2023-12-23 17:46:43 +01:00
parent e38d556531
commit e80801b639
Signed by: darkwiiplayer
GPG Key ID: 7808674088232B3E
1 changed files with 35 additions and 1 deletions

View File

@ -38,6 +38,7 @@ export class State extends EventTarget {
#target
#options
#queue
#forwardCache
constructor(target={}, options={}) {
super()
@ -86,7 +87,17 @@ export class State extends EventTarget {
}
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) {
@ -98,6 +109,10 @@ export class State extends EventTarget {
}
}
const forwardFinalizationRegistry = new FinalizationRegistry(([cache, name]) => {
cache.remove(name)
})
export class ForwardState extends EventTarget {
#backend
#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