Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit cbbee25

Browse files
committed
[ADD] Memory: memory will be use for history, target the node to redraw...
1 parent 6d150c4 commit cbbee25

File tree

8 files changed

+4902
-0
lines changed

8 files changed

+4902
-0
lines changed

packages/core/src/Memory/Memory.ts

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import {
2+
AllowedMemory,
3+
AllowedObject,
4+
MemoryVersionable,
5+
MemoryTypeArray,
6+
MemoryTypeObject,
7+
MemoryTypeSet,
8+
} from './Memory';
9+
import { proxifyObject } from './VersionableObject';
10+
import { proxifyArray } from './VersionableArray';
11+
import { proxifySet } from './VersionableSet';
12+
import {
13+
memoryProxyNotVersionableKey,
14+
NotVersionableErrorMessage,
15+
VersionableAllreadyVersionableErrorMessage,
16+
memoryProxyPramsKey,
17+
} from './const';
18+
19+
export class ProxyUniqID extends Number {}
20+
ProxyUniqID.prototype[memoryProxyNotVersionableKey] = true;
21+
22+
let MemoryID = 0;
23+
export function generateMemoryID(): ProxyUniqID {
24+
// Unique ID (not really related to memory)
25+
return new ProxyUniqID(++MemoryID);
26+
}
27+
28+
// const key = new ProxyUniqID(1);
29+
// const rec = {};
30+
// rec[key as number] = 4;
31+
32+
// Magic memory key that is set on the object through a symbol (inaccessible for
33+
// others). It stores everything that is useful for the memory to handle this object.
34+
export interface VersionableParams {
35+
ID: ProxyUniqID; // id du couple (proxy, object) en mémoire (number extension)
36+
memory?: MemoryVersionable; // interface for versionale to access memory (since we don't want to give them the true memory object !)
37+
proxy: AllowedObject; // proxy itself (what we return, what people actually manipulate)
38+
object: AllowedObject; // Object that is proxified (it is synchronized with the proxy because the proxy updates it at some points ... -- not the Set !)
39+
linkCallback: (memory: MemoryVersionable) => void; // function to call when this versionable is linked to a memory
40+
sync: () => void;
41+
itsme: (obj: AllowedMemory) => boolean;
42+
MemoryType: typeof MemoryTypeObject | typeof MemoryTypeArray | typeof MemoryTypeSet;
43+
willBeRootDiff?: true; // is it a standalone object or does it only makes sense as part of an other object's structure ?
44+
}
45+
46+
// queue of stuff to proxify
47+
const objectStackToProxify = new Map<AllowedMemory, Array<(proxy: AllowedMemory) => void>>();
48+
49+
export function makeVersionable<T extends AllowedMemory>(customClass: T): T {
50+
const params = customClass[memoryProxyPramsKey] as VersionableParams;
51+
if (params) {
52+
if (params.object === customClass) {
53+
VersionableAllreadyVersionableErrorMessage();
54+
}
55+
if (params && params.itsme(customClass)) {
56+
return customClass;
57+
}
58+
}
59+
const proxy = _proxify(customClass);
60+
objectStackToProxify.forEach((callbacks, torototo) => {
61+
objectStackToProxify.delete(torototo);
62+
const proxy = _proxify(torototo);
63+
callbacks.forEach(callback => callback(proxy));
64+
});
65+
return proxy;
66+
}
67+
export function createProxyWithVersionable<T extends AllowedMemory>(
68+
proxy: T,
69+
handler: ProxyHandler<object>,
70+
): T {
71+
const newProxy = new Proxy(proxy as object, handler);
72+
proxy[memoryProxyPramsKey].proxy = newProxy;
73+
return newProxy as T;
74+
}
75+
export function markNotVersionable(customClass: AllowedMemory): void {
76+
customClass[memoryProxyNotVersionableKey] = true;
77+
}
78+
// the argument can be anything actually, not necessarily a class
79+
export function checkIfProxy<T extends AllowedMemory>(customClass: T): T {
80+
if (
81+
typeof customClass !== 'object' ||
82+
customClass === null ||
83+
customClass[memoryProxyNotVersionableKey] // this is set by the user
84+
) {
85+
return customClass;
86+
}
87+
88+
const params = customClass[memoryProxyPramsKey];
89+
if (params) {
90+
if (params.object === customClass) {
91+
VersionableAllreadyVersionableErrorMessage();
92+
}
93+
if (params.itsme(customClass)) {
94+
// Already versioned ! (we could have inherited from the `params` of
95+
// another, already versioned object, but we might not)
96+
return customClass;
97+
}
98+
}
99+
100+
NotVersionableErrorMessage();
101+
}
102+
function _proxify<T extends AllowedMemory>(customClass: T): T {
103+
const params = customClass[memoryProxyPramsKey];
104+
if (params && params.itsme(customClass)) {
105+
return params.proxy;
106+
}
107+
let proxy: T;
108+
if (customClass instanceof Set) {
109+
proxy = proxifySet(customClass) as T;
110+
} else if (customClass instanceof Array) {
111+
proxy = proxifyArray(customClass) as T;
112+
} else {
113+
proxy = proxifyObject(customClass as Record<string, AllowedMemory>) as T;
114+
}
115+
return proxy;
116+
}
117+
// Recursive proxification is very limited because of callback depth. To
118+
// circumvent this issue, we queue the proxification of children.
119+
export function stackedProxify<T extends AllowedMemory>(
120+
customClass: T,
121+
callback: (proxy: T) => void,
122+
): void {
123+
if (
124+
!customClass ||
125+
typeof customClass !== 'object' ||
126+
customClass[memoryProxyNotVersionableKey]
127+
) {
128+
callback(customClass);
129+
return;
130+
}
131+
const params = customClass[memoryProxyPramsKey];
132+
if (params) {
133+
callback(params.proxy);
134+
}
135+
const callbacks = objectStackToProxify.get(customClass) || [];
136+
objectStackToProxify.set(customClass, callbacks);
137+
callbacks.push(callback);
138+
}

0 commit comments

Comments
 (0)