Skip to content

Commit

Permalink
glimmer validator compat (#95)
Browse files Browse the repository at this point in the history
* glimmer-validator-compat

* +
  • Loading branch information
lifeart authored Feb 6, 2024
1 parent 97f7b88 commit dd184fb
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/utils/glimmer-compat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * as caching from './caching-primitives';
export * as destroyable from './destroyable';
export * as storage from './storage-primitives';
export * as validator from './glimmer-validator';
92 changes: 92 additions & 0 deletions src/utils/glimmer-validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import {
type Cell,
cellFor,
cellsMap,
getTracker,
isRendering,
setIsRendering,
} from './reactive';

export { cellFor as tagFor } from '@lifeart/gxt';

export function dirtyTagFor(obj: object, key: string | number | symbol): void {
// @ts-expect-error
const cell = cellFor(obj, key);
cell.update(cell.value);
}
export function tagMetaFor(obj: object): any {
return cellsMap.get(obj);
}

export function isTracking(): boolean {
return getTracker() !== null;
}

export function consumeTag(tag: Cell): void {
const TRACKER = getTracker();
if (TRACKER !== null) {
TRACKER.add(tag);
}
}

export type Getter<T, K extends keyof T> = (self: T) => T[K] | undefined;
export type Setter<T, K extends keyof T> = (self: T, value: T[K]) => void;

export function trackedData<T extends object, K extends keyof T>(
key: K,
initializer?: (this: T) => T[K],
): { getter: Getter<T, K>; setter: Setter<T, K> } {
let values = new WeakMap<T, T[K]>();
let hasInitializer = typeof initializer === 'function';

function getter(self: T) {
consumeTag(cellFor(self, key));

let value;

// If the field has never been initialized, we should initialize it
if (hasInitializer && !values.has(self)) {
value = initializer!.call(self);
values.set(self, value);
} else {
value = values.get(self);
}

return value;
}

function setter(self: T, value: T[K]): void {
dirtyTagFor(self, key);
values.set(self, value);
}

return { getter, setter };
}

let renderingStateBeforeBegin = isRendering();

export function beginTrackFrame() {
renderingStateBeforeBegin = isRendering();
if (!isRendering()) {
setIsRendering(true);
}
}

export function endTrackFrame() {
if (isRendering() !== renderingStateBeforeBegin) {
setIsRendering(renderingStateBeforeBegin);
}
}

export function beginUntrackFrame() {
renderingStateBeforeBegin = isRendering();
if (renderingStateBeforeBegin) {
setIsRendering(false);
}
}

export function endUntrackFrame() {
if (isRendering() !== renderingStateBeforeBegin) {
setIsRendering(renderingStateBeforeBegin);
}
}
33 changes: 20 additions & 13 deletions src/utils/reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const DEBUG_MERGED_CELLS = new Set<MergedCell>();
export const DEBUG_CELLS = new Set<Cell>();
var currentTracker: Set<Cell> | null = null;
let _isRendering = false;
const cellsMap = new WeakMap<object, Record<string, Cell<unknown>>>();
export const cellsMap = new WeakMap<object, Map<string | number | symbol, Cell<unknown>>>();

export function getCells() {
return Array.from(DEBUG_CELLS);
Expand All @@ -40,9 +40,9 @@ if (IS_DEV_MODE) {
}
}

function keysFor(obj: object): Record<string, Cell<unknown>> {
function keysFor(obj: object): Map<string | number | symbol, Cell<unknown>> {
if (!cellsMap.has(obj)) {
cellsMap.set(obj, {});
cellsMap.set(obj, new Map());
}
return cellsMap.get(obj)!;
}
Expand All @@ -56,26 +56,26 @@ export function tracked(
return {
get() {
const keys = keysFor(this);
if (!(key in keys)) {
if (!keys.has(key)) {
const value: any = cell(
hasInitializer
? descriptor!.initializer?.call(this)
: descriptor?.value,
`${klass.constructor.name}.${key}.@tracked`,
);
keys[key] = value;
keys.set(key, value);
return value.value;
} else {
return keys[key].value;
return keys.get(key)!.value;
}
},
set(newValue: any) {
const keys = keysFor(this);
if (!(key in keys)) {
keys[key] = cell(newValue, `${klass.constructor.name}.${key}.@tracked`);
if (!keys.has(key)) {
keys.set(key, cell(newValue, `${klass.constructor.name}.${key}.@tracked`));
return;
}
const _cell = keys[key];
const _cell = keys.get(key)!;
if (_cell.value === newValue) {
return;
}
Expand Down Expand Up @@ -278,15 +278,15 @@ export function cellFor<T extends object, K extends keyof T>(
obj: T,
key: K,
): Cell<T[K]> {
const refs = cellsMap.get(obj) || {};
if (key in refs) {
return refs[key as unknown as string] as Cell<T[K]>;
const refs = cellsMap.get(obj) || new Map<string | number | symbol, Cell>();
if (refs.has(key)) {
return refs.get(key) as Cell<T[K]>;
}
const cellValue = new Cell<T[K]>(
obj[key],
`${obj.constructor.name}.${String(key)}`,
);
refs[key as unknown as string] = cellValue;
refs.set(key, cellValue);
cellsMap.set(obj, refs);
Object.defineProperty(obj, key, {
get() {
Expand Down Expand Up @@ -326,3 +326,10 @@ export function inNewTrackingFrame(callback: () => void) {
callback();
currentTracker = existingTracker;
}

export function getTracker() {
return currentTracker;
}
export function setTracker(tracker: Set<Cell> | null) {
currentTracker = tracker;
}

0 comments on commit dd184fb

Please sign in to comment.