| 18 | |
| 19 | /** |
| 20 | * MUTABLE-OBJECT DISPOSITION (ruling B3's cache inventory, ruling B12): this |
| 21 | * is the engine's one GLOBAL, STRONG value retainer — its entries live as long |
| 22 | * as the engine and are held by name, not weakly — so **no entry may ever hold |
| 23 | * a `BoxedObject`, directly or nested inside a value**. An object stored here |
| 24 | * would survive every scope, outliving the program's last reference to it, and |
| 25 | * an object-derived entry could never be invalidated (a field store advances |
| 26 | * no engine axis and this store records no dependencies). |
| 27 | * |
| 28 | * The rule is upheld by what gets stored, not by machinery: the five named |
| 29 | * caches built through it hold rule sets and constant tables (simplification |
| 30 | * rules, univariate-root rules, harmonization rules, the constructible |
| 31 | * trigonometric-value tables), all built from the standard library and from |
| 32 | * literals, with no route to a user value. It is pinned adversarially by a |
| 33 | * test rather than by a guard, because adding a containment scan to a |
| 34 | * name-keyed store of arbitrary payloads would cost every build a walk to |
| 35 | * defend against a case no caller can currently produce. |
| 36 | */ |
| 37 | export class EngineCacheStore { |
| 38 | private _entries: Record<string, CacheEntry> = {}; |
| 39 | |
| 40 | getOrBuild<T>( |
| 41 | cacheName: string, |