{"version":3,"sources":["../../../../src/lib/AreRoot/AreRootCache.context.ts"],"names":[],"mappings":"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","file":"AreRootCache.context.mjs","sourcesContent":["import { A_Fragment } from \"@adaas/a-concept\";\nimport { A_Frame } from \"@adaas/a-frame/core\";\nimport { AreNode } from \"@adaas/are\";\n\n\n/**\n * A single cached, detached component subtree for an are-root outlet.\n *\n * `node` is fully compiled and its scene plan is intact (it was `unmount()`ed,\n * not destroyed), so it can be re-mounted instantly without re-tokenizing,\n * re-loading, transforming or compiling. `subscribers` records the exact set of\n * nodes inside the subtree that were subscribed to the signal bus at the moment\n * of stashing — they are unsubscribed while cached (so the detached DOM never\n * reacts to signals) and re-subscribed verbatim on restore.\n */\nexport type AreRootCacheEntry = {\n    node: AreNode;\n    subscribers: AreNode[];\n};\n\n\n@A_Frame.Define({\n    namespace: 'a-are-html',\n    description: 'AreRootCache is a fragment that keeps a small per-root LRU of previously rendered are-root subtrees. When an are-root swaps the component it displays, the outgoing subtree is stashed here (unmounted + detached, but not destroyed) so that routing back to it can re-inject the preserved scene instantly instead of rebuilding from scratch.'\n})\nexport class AreRootCache extends A_Fragment {\n\n    /**\n     * rootId -> (component tag -> cache entry). The inner Map preserves\n     * insertion order which is used as the LRU recency order: the first key is\n     * the least-recently-used entry, the last key the most-recently-used.\n     */\n    protected _cache: Map<string, Map<string, AreRootCacheEntry>> = new Map();\n\n    /**\n     * Maximum number of cached subtrees kept per root. Older entries beyond this\n     * limit are evicted (and returned to the caller so it can destroy them).\n     */\n    protected _limit: number;\n\n    constructor(limit: number = 10) {\n        super({ name: 'AreRootCache' });\n        this._limit = Math.max(0, Math.floor(limit));\n    }\n\n    /**\n     * Maximum number of cached subtrees kept per root.\n     */\n    get limit(): number {\n        return this._limit;\n    }\n\n    protected bucket(rootId: string): Map<string, AreRootCacheEntry> {\n        let bucket = this._cache.get(rootId);\n        if (!bucket) {\n            bucket = new Map();\n            this._cache.set(rootId, bucket);\n        }\n        return bucket;\n    }\n\n    /**\n     * Whether a subtree for the given component tag is currently cached.\n     */\n    has(rootId: string, tag: string): boolean {\n        return this.bucket(rootId).has(tag);\n    }\n\n    /**\n     * Retrieve AND remove a cached subtree so it can become live again. Returns\n     * `undefined` on a cache miss.\n     */\n    take(rootId: string, tag: string): AreRootCacheEntry | undefined {\n        const bucket = this.bucket(rootId);\n        const entry = bucket.get(tag);\n        if (entry) {\n            bucket.delete(tag);\n        }\n        return entry;\n    }\n\n    /**\n     * Stash a detached subtree under the given component tag. Returns any entries\n     * that were evicted to honour the LRU limit (or replaced for the same tag) so\n     * the caller can `destroy()` them.\n     */\n    put(rootId: string, tag: string, entry: AreRootCacheEntry): AreRootCacheEntry[] {\n        const bucket = this.bucket(rootId);\n        const evicted: AreRootCacheEntry[] = [];\n\n        // Replace any stale entry for the same tag (should not normally happen,\n        // since a displayed tag is never simultaneously cached) and surface it\n        // for destruction so it does not leak.\n        const existing = bucket.get(tag);\n        if (existing) {\n            bucket.delete(tag);\n            if (existing.node !== entry.node) {\n                evicted.push(existing);\n            }\n        }\n\n        // A limit of 0 disables caching: the freshly added entry is evicted\n        // immediately so the caller tears it down.\n        bucket.set(tag, entry);\n\n        while (bucket.size > this._limit) {\n            const oldestKey = bucket.keys().next().value as string | undefined;\n            if (oldestKey === undefined) {\n                break;\n            }\n            const oldest = bucket.get(oldestKey)!;\n            bucket.delete(oldestKey);\n            evicted.push(oldest);\n        }\n\n        return evicted;\n    }\n\n    /**\n     * Remove and return every cached entry for a root (e.g. on teardown) so the\n     * caller can destroy them.\n     */\n    clear(rootId: string): AreRootCacheEntry[] {\n        const bucket = this._cache.get(rootId);\n        if (!bucket) {\n            return [];\n        }\n        const entries = [...bucket.values()];\n        bucket.clear();\n        this._cache.delete(rootId);\n        return entries;\n    }\n}\n"]}