vlens
Version:
Data Centric Routing & Rendering Mini-Framework
73 lines (59 loc) • 1.5 kB
text/typescript
import * as cache from "./cache"
function _sequentialGenerator() {
let _id = 0;
return (): number => {
let res = _id;
_id += 1;
return res;
}
}
const nextObjectId = _sequentialGenerator();
let idmap = new Map<unknown, number>()
let objmap = new Map<number, unknown>()
export function objectId(obj: unknown): number {
let v = idmap.get(obj)
if (v === undefined) {
v = nextObjectId()
idmap.set(obj, v)
objmap.set(v, obj)
}
return v
}
export function objectById<T = any>(id: number): T | null {
return objmap.get(id) as T ?? null;
}
export function clearRefs() {
idmap.clear()
objmap.clear()
}
declare const _ref_type: unique symbol;
export type Ref<T = any> = RawRef & {
[_ref_type]: T
}
export type RawRef<T = any> = {
obj: T;
key: keyof T;
}
function _ref<T, K extends keyof T>(obj: T, key: K): Ref<T[K]> {
return { obj, key } as Ref<T[K]>
}
// returns a stable Ref: same identity when called with the same (obj, key) pair
// across re-renders.
export function ref<T, K extends keyof T>(obj: T, key: K): Ref<T[K]> {
// circular import!!
return cache.fn(_ref, obj, key)
}
export function value<T>(r: Ref<T>, v?: T): T {
if (v !== undefined) {
r.obj[r.key] = v
return v
} else {
return r.obj[r.key]
}
}
export function get<T>(r: Ref<T>): T {
return r.obj[r.key]
}
export function set<T>(r: Ref<T>, value: T) {
r.obj[r.key] = value
}