Convert Links to ES6 Map & LLink Serialisation (#246)

* Fix intermittent links bug - graph.links Map()

Replaces graph.links with Map()
Adds a Proxy to provide for...in and indexer access
Temporarily uses merged Map+Record type, to ease downstream migration

* nit - Remove redundant code

* nit - Remove redundant null checks

* Add Serializable interface, used in LLink

Allows LLink to be serialised as an object rather than an array, bringing it inline with the rest of LiteGraph.
This commit is contained in:
filtered
2024-11-01 12:53:00 +11:00
committed by GitHub
parent eaaa0a4c39
commit 020c912a8d
6 changed files with 200 additions and 102 deletions

55
src/MapProxyHandler.ts Normal file
View File

@@ -0,0 +1,55 @@
/** Temporary workaround until downstream consumers migrate to Map. A brittle wrapper with many flaws, but should be fine for simple maps using int indexes. */
export class MapProxyHandler<V> implements ProxyHandler<Map<number | string, V>> {
getOwnPropertyDescriptor(target: Map<number | string, V>, p: string | symbol): PropertyDescriptor | undefined {
const value = this.get(target, p)
if (value) return {
configurable: true,
enumerable: true,
value
}
}
has(target: Map<number | string, V>, p: string | symbol): boolean {
if (typeof p === "symbol") return false
const int = parseInt(p, 10)
return target.has(!isNaN(int) ? int : p)
}
ownKeys(target: Map<number | string, V>): ArrayLike<string | symbol> {
return [...target.keys()].map(x => String(x))
}
get(target: Map<number | string, V>, p: string | symbol): any {
// Workaround does not support link IDs of "values", "entries", "constructor", etc.
if (p in target) return Reflect.get(target, p, target)
if (typeof p === "symbol") return
const int = parseInt(p, 10)
return target.get(!isNaN(int) ? int : p)
}
set(target: Map<number | string, V>, p: string | symbol, newValue: any): boolean {
if (typeof p === "symbol") return false
const int = parseInt(p, 10)
target.set(!isNaN(int) ? int : p, newValue)
return true
}
deleteProperty(target: Map<number | string, V>, p: string | symbol): boolean {
return target.delete(p as number | string)
}
static bindAllMethods(map: Map<any, any>): void {
map.clear = map.clear.bind(map)
map.delete = map.delete.bind(map)
map.forEach = map.forEach.bind(map)
map.get = map.get.bind(map)
map.has = map.has.bind(map)
map.set = map.set.bind(map)
map.entries = map.entries.bind(map)
map.keys = map.keys.bind(map)
map.values = map.values.bind(map)
}
}