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

Commit 418095d

Browse files
committed
memory: sync at switch
1 parent 13bd066 commit 418095d

File tree

10 files changed

+140
-166
lines changed

10 files changed

+140
-166
lines changed

packages/core/src/Memory/Memory.ts

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ export interface MemoryVersionable {
8585
getSlice: () => object;
8686
getSliceValue: (ID: ProxyUniqID) => MemoryCompiled;
8787
isFrozen: () => boolean;
88-
isDirty: (ID: ProxyUniqID) => boolean;
8988
markDirty: (ID: ProxyUniqID) => void;
90-
markAsLoaded: (ID: ProxyUniqID) => boolean;
9189
addSliceProxyParent: (ID: ProxyUniqID, parentID: ProxyUniqID, attributeName: string) => boolean;
9290
deleteSliceProxyParent: (
9391
ID: ProxyUniqID,
@@ -140,7 +138,6 @@ export class Memory {
140138
_sliceKey: sliceKey; // identifier or current memory slice
141139
_references: Record<sliceKey, MemoryReference> = {}; // Record<children, parent>
142140
_currentReference: MemoryReference; // Record<children, parent>
143-
_invalideCache: Record<number, boolean> = {}; // paths which have been set but not read again yet (after the set)
144141
_proxies: Record<number, object> = {};
145142
_rootProxies: Record<number, boolean> = {};
146143
_memoryVersionable: MemoryVersionable;
@@ -157,16 +154,10 @@ export class Memory {
157154
getSlice: (): Record<number, MemoryType> => this._currentReference.slice,
158155
getSliceValue: (ID: ProxyUniqID): MemoryCompiled => this._getValue(this._sliceKey, ID),
159156
isFrozen: this.isFrozen.bind(this),
160-
// Is currently dirty (we may have switched from a slice to a very
161-
// different one, thus setting "dirty" on a lot of objects along the
162-
// way, all the ones that were modified at one point)
163-
// Is your proxy unsynchronized
164-
isDirty: (ID: ProxyUniqID): boolean => this._invalideCache[ID as number],
165157
// Mark as "modified" in this slice
166158
markDirty: (ID: ProxyUniqID): boolean =>
167159
(this._currentReference.invalideCache[ID as number] = true),
168160
// I am the proxy, I tell you I synchornized the value
169-
markAsLoaded: (ID: ProxyUniqID): boolean => (this._invalideCache[ID as number] = false),
170161
deleteSliceProxyParent: this._deleteSliceProxyParent.bind(this),
171162
addSliceProxyParent: this._addSliceProxyParent.bind(this),
172163
linkToMemory: this._linkToMemory.bind(this),
@@ -215,14 +206,27 @@ export class Memory {
215206
}
216207
getChangedVersionables(sliceKey: sliceKey = this._sliceKey): Map<AllowedObject, string[][]> {
217208
const pathChanges = new Map<AllowedObject, string[][]>();
218-
const invalideCache = this._references[sliceKey].invalideCache;
219-
for (const id in invalideCache) {
209+
const slice = this._references[sliceKey].slice;
210+
for (const id in slice) {
211+
const item = slice[id];
220212
const proxy = this._proxies[id] as LoopObject | LoopArray | LoopSet;
221213
this._getRootVersionables(this._sliceKey, proxy).forEach(pathToRoot => {
214+
let paths: string[][];
215+
if (
216+
(item instanceof MemoryTypeObject || item instanceof MemoryTypeArray) &&
217+
Object.keys(item.props).length
218+
) {
219+
paths = [];
220+
for (const key in item.props) {
221+
paths.push(pathToRoot.path.concat([key]));
222+
}
223+
} else {
224+
paths = [pathToRoot.path];
225+
}
222226
if (pathChanges.get(pathToRoot.proxy)) {
223-
pathChanges.get(pathToRoot.proxy).push(pathToRoot.path);
227+
pathChanges.get(pathToRoot.proxy).push(...paths);
224228
} else {
225-
pathChanges.set(pathToRoot.proxy, [pathToRoot.path]);
229+
pathChanges.set(pathToRoot.proxy, paths);
226230
}
227231
});
228232
}
@@ -242,7 +246,7 @@ export class Memory {
242246
if (!params.itsme(proxy)) {
243247
return NotVersionableErrorMessage();
244248
}
245-
if (params.memory !== this._memoryVersionable) {
249+
if (!params.memory || params.memory !== this._memoryVersionable) {
246250
params.willBeRootDiff = true;
247251
this._linkToMemory(proxy);
248252
}
@@ -304,15 +308,24 @@ export class Memory {
304308
refs.shift();
305309
}
306310

311+
const invalideCache = new Set<number>();
307312
while (refs.length) {
308313
const ref = refs.pop();
309314
Object.keys(ref.invalideCache).forEach(key => {
310315
// It was invalid before, it is still invalid now since it wasn't yet read
311-
this._invalideCache[key] = true;
316+
invalideCache.add(+key);
312317
});
313318
}
319+
314320
this._currentReference = this._references[sliceKey];
315321
this._sliceKey = sliceKey;
322+
323+
for (const key of invalideCache) {
324+
const proxy = this._proxies[key];
325+
const params = proxy[memoryProxyPramsKey] as VersionableParams;
326+
params.sync();
327+
}
328+
316329
return this;
317330
}
318331
snapshot(fromSliceKey: sliceKey, unitSliceKey: sliceKey, newSliceKey: sliceKey): void {
@@ -416,9 +429,9 @@ export class Memory {
416429
continue;
417430
}
418431
this._getProxyParentedPath(sliceKey, nodeID).forEach(path => {
419-
const nodeID = path.split(parentedPathSeparator, 1)[0];
420-
const partPath = path.slice(nodeID.length + 1);
421-
pathList.push([+nodeID, [partPath].concat(pathToNode)]);
432+
const parentNodeID = path.split(parentedPathSeparator, 1)[0];
433+
const partPath = path.slice(parentNodeID.length + 1);
434+
pathList.push([+parentNodeID, [partPath].concat(pathToNode)]);
422435
});
423436
}
424437
return roots;

packages/core/src/Memory/VersionableArray.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from './const';
1616
import {
1717
proxifyObject,
18+
GettersSetters,
1819
ProxyObjectHandler,
1920
proxyObjectHandler,
2021
keyType,
@@ -34,19 +35,15 @@ interface ArrayParams extends VersionableParams {
3435
map: Map<AllowedMemory, uniqID>;
3536
syncSlice?: Record<number, MemoryType>;
3637
previousSliceValues?: uniqIDMemoryTypeValues;
38+
proto: GettersSetters;
3739
}
3840

3941
const proxyArrayHandler = {
40-
get(proxyObject: AllowedMemory[], prop: keyType, proxy: object): AllowedMemory {
41-
const params = proxyObject[memoryProxyPramsKey];
42-
const array = params.object;
43-
if (typeof prop === 'symbol') {
44-
return proxyObjectHandler.get(array, prop, proxy);
45-
}
46-
if (!isNaN(prop as number)) {
47-
params.sync();
42+
get(array: AllowedMemory[], prop: keyType, proxy: object): AllowedMemory {
43+
if (typeof prop === 'symbol' || !isNaN(prop as number)) {
4844
return array[prop];
4945
}
46+
const params = array[memoryProxyPramsKey];
5047
if (!params.memory) {
5148
return proxyObjectHandler.get(array, prop, proxy);
5249
}
@@ -91,7 +88,6 @@ const proxyArrayHandler = {
9188
}
9289

9390
value = checkIfProxy(value);
94-
params.sync();
9591
const oldValue = array[prop];
9692

9793
if (oldValue === value || (value === removedItem && !(prop in array))) {
@@ -246,7 +242,6 @@ export function proxifyArray<T extends AllowedMemory>(array: T[]): T[] {
246242
}
247243

248244
function unshift(params: ArrayParams, ...items: AllowedMemory[]): number {
249-
params.sync();
250245
for (let k = 0, len = items.length; k < len; k++) {
251246
const item = items[k];
252247
params.object.unshift(Undefined);
@@ -256,15 +251,13 @@ function unshift(params: ArrayParams, ...items: AllowedMemory[]): number {
256251
return params.object.length;
257252
}
258253
function shift(params: ArrayParams): AllowedMemory {
259-
params.sync();
260254
const value = params.object[0];
261255
this['0'] = removedItem;
262256
params.object.shift();
263257
params.uniqIDs.shift();
264258
return value;
265259
}
266260
function pop(params: ArrayParams): AllowedMemory {
267-
params.sync();
268261
const lastIndex = params.object.length - 1;
269262
const value = params.object[lastIndex];
270263
this.length = lastIndex;
@@ -276,7 +269,6 @@ function splice(
276269
nb: number,
277270
...items: AllowedMemory[]
278271
): AllowedMemory[] {
279-
params.sync();
280272
const array = params.object;
281273
const uniqIDs = params.uniqIDs;
282274
const len = array.length;
@@ -308,7 +300,6 @@ function forEach(
308300
params: ArrayParams,
309301
callback: (value: AllowedMemory, index: number, array: AllowedMemory[]) => void,
310302
): void {
311-
params.sync();
312303
const array = params.object;
313304
for (let index = 0, len = array.length; index < len; index++) {
314305
callback(array[index], index, this);
@@ -319,7 +310,6 @@ function map(
319310
callback: (value: AllowedMemory, index: number, array: AllowedMemory[]) => AllowedMemory,
320311
): AllowedMemory[] {
321312
const result = [];
322-
params.sync();
323313
const array = params.object;
324314
for (let index = 0, len = array.length; index < len; index++) {
325315
result.push(callback(array[index], index, this));
@@ -331,7 +321,6 @@ function filter(
331321
callback: (value: AllowedMemory, index: number, array: AllowedMemory[]) => boolean,
332322
): AllowedMemory[] {
333323
const result = [];
334-
params.sync();
335324
const array = params.object;
336325
for (let index = 0, len = array.length; index < len; index++) {
337326
const value = array[index];
@@ -342,7 +331,6 @@ function filter(
342331
return result;
343332
}
344333
function indexOf(params: ArrayParams, item: AllowedMemory): number {
345-
params.sync();
346334
const uniqID = params.map.get(item);
347335
if (uniqID === undefined) {
348336
return -1;
@@ -369,12 +357,11 @@ function indexOf(params: ArrayParams, item: AllowedMemory): number {
369357
return index;
370358
}
371359
function proxifySyncArray(): { compiled: uniqIDMemoryTypeValues; sequences: uniqID[] } {
360+
// Synchronization function
361+
// Most methods of the "proxy" will call this synchronization function, even
362+
// if it is not yet linked to a memory !
372363
const params = this as ArrayParams;
373364
const memory = params.memory;
374-
if (!memory.isDirty(params.ID)) {
375-
return;
376-
}
377-
memory.markAsLoaded(params.ID);
378365
// empties the array
379366
params.uniqIDs.length = 0;
380367
params.object.length = 0;

0 commit comments

Comments
 (0)