Skip to content

Commit 75d718e

Browse files
committed
glimmer-validator-compat
1 parent 97f7b88 commit 75d718e

File tree

3 files changed

+78
-13
lines changed

3 files changed

+78
-13
lines changed

src/utils/glimmer-compat.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * as caching from './caching-primitives';
2+
export * as destroyable from './destroyable';
3+
export * as storage from './storage-primitives';
4+
export * as validator from './glimmer-validator';

src/utils/glimmer-validator.ts

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Cell, cellFor, cellsMap, getTracker } from './reactive';
2+
3+
export { cellFor as tagFor } from '@lifeart/gxt';
4+
5+
export function dirtyTagFor(obj: object, key: string | number | symbol): void {
6+
// @ts-expect-error
7+
const cell = cellFor(obj, key);
8+
cell.update(cell.value);
9+
}
10+
export function tagMetaFor(obj: object): any {
11+
return cellsMap.get(obj);
12+
}
13+
14+
export function isTracking(): boolean {
15+
return getTracker() !== null;
16+
}
17+
18+
export function consumeTag(tag: Cell): void {
19+
const TRACKER = getTracker();
20+
if (TRACKER !== null) {
21+
TRACKER.add(tag);
22+
}
23+
}
24+
25+
export type Getter<T, K extends keyof T> = (self: T) => T[K] | undefined;
26+
export type Setter<T, K extends keyof T> = (self: T, value: T[K]) => void;
27+
28+
export function trackedData<T extends object, K extends keyof T>(
29+
key: K,
30+
initializer?: (this: T) => T[K],
31+
): { getter: Getter<T, K>; setter: Setter<T, K> } {
32+
let values = new WeakMap<T, T[K]>();
33+
let hasInitializer = typeof initializer === 'function';
34+
35+
function getter(self: T) {
36+
consumeTag(cellFor(self, key));
37+
38+
let value;
39+
40+
// If the field has never been initialized, we should initialize it
41+
if (hasInitializer && !values.has(self)) {
42+
value = initializer!.call(self);
43+
values.set(self, value);
44+
} else {
45+
value = values.get(self);
46+
}
47+
48+
return value;
49+
}
50+
51+
function setter(self: T, value: T[K]): void {
52+
dirtyTagFor(self, key);
53+
values.set(self, value);
54+
}
55+
56+
return { getter, setter };
57+
}

src/utils/reactive.ts

+17-13
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const DEBUG_MERGED_CELLS = new Set<MergedCell>();
2121
export const DEBUG_CELLS = new Set<Cell>();
2222
var currentTracker: Set<Cell> | null = null;
2323
let _isRendering = false;
24-
const cellsMap = new WeakMap<object, Record<string, Cell<unknown>>>();
24+
export const cellsMap = new WeakMap<object, Map<string | number | symbol, Cell<unknown>>>();
2525

2626
export function getCells() {
2727
return Array.from(DEBUG_CELLS);
@@ -40,9 +40,9 @@ if (IS_DEV_MODE) {
4040
}
4141
}
4242

43-
function keysFor(obj: object): Record<string, Cell<unknown>> {
43+
function keysFor(obj: object): Map<string | number | symbol, Cell<unknown>> {
4444
if (!cellsMap.has(obj)) {
45-
cellsMap.set(obj, {});
45+
cellsMap.set(obj, new Map());
4646
}
4747
return cellsMap.get(obj)!;
4848
}
@@ -56,26 +56,26 @@ export function tracked(
5656
return {
5757
get() {
5858
const keys = keysFor(this);
59-
if (!(key in keys)) {
59+
if (!keys.has(key)) {
6060
const value: any = cell(
6161
hasInitializer
6262
? descriptor!.initializer?.call(this)
6363
: descriptor?.value,
6464
`${klass.constructor.name}.${key}.@tracked`,
6565
);
66-
keys[key] = value;
66+
keys.set(key, value);
6767
return value.value;
6868
} else {
69-
return keys[key].value;
69+
return keys.get(key)!.value;
7070
}
7171
},
7272
set(newValue: any) {
7373
const keys = keysFor(this);
74-
if (!(key in keys)) {
75-
keys[key] = cell(newValue, `${klass.constructor.name}.${key}.@tracked`);
74+
if (!keys.has(key)) {
75+
keys.set(key, cell(newValue, `${klass.constructor.name}.${key}.@tracked`));
7676
return;
7777
}
78-
const _cell = keys[key];
78+
const _cell = keys.get(key)!;
7979
if (_cell.value === newValue) {
8080
return;
8181
}
@@ -278,15 +278,15 @@ export function cellFor<T extends object, K extends keyof T>(
278278
obj: T,
279279
key: K,
280280
): Cell<T[K]> {
281-
const refs = cellsMap.get(obj) || {};
282-
if (key in refs) {
283-
return refs[key as unknown as string] as Cell<T[K]>;
281+
const refs = cellsMap.get(obj) || new Map<string | number | symbol, Cell>();
282+
if (refs.has(key)) {
283+
return refs.get(key) as Cell<T[K]>;
284284
}
285285
const cellValue = new Cell<T[K]>(
286286
obj[key],
287287
`${obj.constructor.name}.${String(key)}`,
288288
);
289-
refs[key as unknown as string] = cellValue;
289+
refs.set(key, cellValue);
290290
cellsMap.set(obj, refs);
291291
Object.defineProperty(obj, key, {
292292
get() {
@@ -326,3 +326,7 @@ export function inNewTrackingFrame(callback: () => void) {
326326
callback();
327327
currentTracker = existingTracker;
328328
}
329+
330+
export function getTracker() {
331+
return currentTracker;
332+
}

0 commit comments

Comments
 (0)