1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-14 23:45:37 +00:00

increase state consistency of generator code

This commit is contained in:
✨ Audrey ✨
2025-04-28 13:24:50 -04:00
parent 69857a057a
commit 016508d245
4 changed files with 951 additions and 779 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,8 @@ import {
pairwise,
MonoTypeOperatorFunction,
Cons,
scan,
filter,
} from "rxjs";
import { ObservableTuple } from "./rx.rxjs";
@@ -245,3 +247,52 @@ export function pin<T>(options?: {
}),
);
}
/** maps a value to a source and keeps a LRC cache of the results
* @param mapResult - maps the stream to a result; this function must return
* a value. It must not return null or undefined.
* @param options.size - the number of entries in the cache
* @param options.key - maps the source to a cache key
* @remarks - LRC is least recently created
*/
export function memoizedMap<Source, Result extends NonNullable<any>>(
mapResult: (source: Source) => Result,
options?: { size?: number; key?: (source: Source) => unknown },
): OperatorFunction<Source, Result> {
return pipe(
// scan's accumulator contains the cache
scan(
([cache], source) => {
const key: unknown = options?.key?.(source) ?? source;
// cache hit?
let result = cache?.get(key);
if (result) {
return [cache, result] as const;
}
// cache miss
result = mapResult(source);
cache?.set(key, result);
// trim cache
const overage = cache.size - (options?.size ?? 1);
if (overage > 0) {
Array.from(cache?.keys() ?? [])
.slice(0, overage)
.forEach((k) => cache?.delete(k));
}
return [cache, result] as const;
},
// FIXME: upgrade to a least-recently-used cache
[new Map(), null] as [Map<unknown, Result>, Source | null],
),
// encapsulate cache
map(([, result]) => result),
// preserve `NonNullable` constraint on `Result`
filter((result): result is Result => !!result),
);
}