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

Commit 754b409

Browse files
committed
memory integration
1 parent 3c61ccd commit 754b409

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+770
-510
lines changed

packages/bundle-odoo-website-editor/OdooWebsiteEditor.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ export class OdooWebsiteEditor extends JWEditor {
6565
constructor(options: OdooWebsiteEditorOption) {
6666
super();
6767
class CustomPlugin extends JWPlugin {
68-
commands = options.customCommands;
68+
commands = Object.assign(
69+
{ commit: { handler: options.afterRender } },
70+
options.customCommands,
71+
);
6972
}
7073

7174
this.configure({
@@ -199,7 +202,6 @@ export class OdooWebsiteEditor extends JWEditor {
199202
['editable', ['main']],
200203
],
201204
location: options.location,
202-
afterRender: options.afterRender,
203205
});
204206
this.configure(DomEditable, {
205207
autoFocus: true,
@@ -223,7 +225,7 @@ export class OdooWebsiteEditor extends JWEditor {
223225
}
224226

225227
async render(): Promise<void> {
226-
const domLayout = this.plugins.get(DomLayout);
227-
return domLayout.redraw();
228+
// const domLayout = this.plugins.get(DomLayout);
229+
// return domLayout._redrawAfterCommand();
228230
}
229231
}

packages/core/src/Core.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class Core<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
8585
previousSibling.removeBackward();
8686
} else if (range.startContainer.breakable && range.startContainer.editable) {
8787
// Otherwise set range start at previous valid leaf.
88-
let ancestor = range.start.parent;
88+
let ancestor: VNode = range.start.parent;
8989
while (ancestor?.breakable && ancestor.editable && !ancestor.previousSibling()) {
9090
ancestor = ancestor.parent;
9191
}
@@ -113,7 +113,7 @@ export class Core<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
113113
nextSibling.removeForward();
114114
} else if (range.endContainer.breakable && range.endContainer.editable) {
115115
// Otherwise set range end at next valid leaf.
116-
let ancestor = range.end.parent;
116+
let ancestor: VNode = range.end.parent;
117117
while (ancestor?.breakable && ancestor.editable && !ancestor.nextSibling()) {
118118
ancestor = ancestor.parent;
119119
}

packages/core/src/Dispatcher.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,13 @@ export class Dispatcher {
105105
await hookCallback(args, signal);
106106
}
107107
}
108+
109+
/**
110+
* Dispatch the commit signal.
111+
*/
112+
async commit(): Promise<void> {
113+
for (const hookCallback of this.commandHooks.commit) {
114+
await hookCallback({}, 'commit');
115+
}
116+
}
108117
}

packages/core/src/JWEditor.ts

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { ModeError } from '../../utils/src/errors';
99
import { ContainerNode } from './VNodes/ContainerNode';
1010
import { AtomicNode } from './VNodes/AtomicNode';
1111
import { SeparatorNode } from './VNodes/SeparatorNode';
12+
import { Memory } from './Memory/Memory';
13+
import { makeVersionable } from './Memory/Versionable';
14+
import { VersionableArray } from './Memory/VersionableArray';
1215

1316
export enum Mode {
1417
CONFIGURATION = 'configuration',
@@ -57,13 +60,12 @@ export class JWEditor {
5760
plugins: [],
5861
loadables: {},
5962
};
63+
memory: Memory;
64+
memoryID = 0;
65+
private memoryInfo: { commandNames: string[] };
6066
selection = new VSelection();
6167
loaders: Record<string, Loader> = {};
6268
private mutex = Promise.resolve();
63-
// Use a set so that when asynchronous functions are called we ensure that
64-
// each command batch is waited for.
65-
preventRenders: Set<Function> = new Set();
66-
enableRender = true;
6769

6870
constructor() {
6971
this.dispatcher = new Dispatcher(this);
@@ -98,9 +100,18 @@ export class JWEditor {
98100
}
99101
}
100102

103+
// create memory
104+
this.memoryInfo = makeVersionable({ commandNames: [] });
105+
this.memory = new Memory();
106+
this.memory.linkToMemory(this.memoryInfo);
107+
101108
for (const plugin of this.plugins.values()) {
102109
await plugin.start();
103110
}
111+
112+
// create the next memory slice (and freeze the current memory)
113+
this.memoryID++;
114+
this.memory.create(this.memoryID.toString());
104115
}
105116

106117
//--------------------------------------------------------------------------
@@ -271,11 +282,16 @@ export class JWEditor {
271282
}
272283
}
273284

285+
/**
286+
* Execute arbitrary code in `callback`, then dispatch the commit event.
287+
*
288+
* @param callback
289+
*/
274290
async execBatch(callback: () => Promise<void>): Promise<void> {
275-
this.preventRenders.add(callback);
276-
await callback();
277-
this.preventRenders.delete(callback);
278-
await this.dispatcher.dispatchHooks('@batch');
291+
return this._execBatchInMemory(() => {
292+
this.memoryInfo.commandNames.push('@batch');
293+
return callback();
294+
});
279295
}
280296

281297
/**
@@ -288,23 +304,49 @@ export class JWEditor {
288304
commandName: C,
289305
params?: CommandParams<P, C>,
290306
): Promise<void> {
291-
return await this.dispatcher.dispatch(commandName, params);
307+
await this._execBatchInMemory(() => {
308+
this.memoryInfo.commandNames.push(commandName);
309+
return this.dispatcher.dispatch(commandName, params);
310+
});
292311
}
293312

294313
/**
295-
* Execute arbitrary code in `callback`, then dispatch the event.
314+
* Execute arbitrary code in `callback` in a free memory slice.
315+
* Return true if we open a memory slice.
316+
*
317+
* TODO: create memory for each plugin who use the command then use
318+
* squashInto(winnerSliceKey, winnerSliceKey, newMasterSliceKey)
319+
*
320+
* @param callback
296321
*/
297-
async execCustomCommand<P extends JWPlugin, C extends Commands<P> = Commands<P>>(
298-
callback: () => Promise<void>,
299-
): Promise<void> {
322+
private async _execBatchInMemory(callback: () => Promise<void>): Promise<void> {
323+
const isFrozen = !this.memoryID || this.memory.isFrozen();
324+
if (isFrozen) {
325+
// Switch to the next memory slice (unfreeze the memory).
326+
this.memory.switchTo(this.memoryID.toString());
327+
this.memoryInfo.commandNames = new VersionableArray<string>();
328+
}
300329
await callback();
301-
await this.dispatcher.dispatchHooks('@custom');
330+
if (isFrozen) {
331+
// Check if it's frozen for calling execCommand inside a call of
332+
// execCommand Create the next memory slice (and freeze the
333+
// current memory).
334+
this.memoryID++;
335+
this.memory.create(this.memoryID.toString());
336+
await this.dispatcher.commit();
337+
}
302338
}
303339

304340
/**
305341
* Stop this editor instance.
306342
*/
307343
async stop(): Promise<void> {
344+
if (this.memory) {
345+
// Unfreeze the memory.
346+
this.memory.create('stop');
347+
this.memory.switchTo('stop');
348+
this.memory = null;
349+
}
308350
for (const plugin of this.plugins.values()) {
309351
await plugin.stop();
310352
}

packages/core/src/Memory/VersionableSet.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,5 +316,7 @@ function linkVersionable(memory: MemoryVersionable): void {
316316
}
317317

318318
export function proxifySet<T extends AllowedMemory>(set: Set<T>): VersionableSet {
319-
return new VersionableSet(set);
319+
const versionableSet = new VersionableSet(set);
320+
set[memoryProxyPramsKey] = versionableSet[memoryProxyPramsKey];
321+
return versionableSet;
320322
}

packages/core/src/Memory/test/memory.perf.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ describe('test performances', () => {
309309
}
310310
}
311311

312-
console.log(
312+
console.info(
313313
'Time to load ' +
314314
nodesNb +
315315
' nodes and ' +
@@ -323,7 +323,7 @@ describe('test performances', () => {
323323
const d2 = Date.now();
324324
readAll(section);
325325
const dt2 = Date.now() - d2;
326-
console.log(
326+
console.info(
327327
'Time to re-load ' +
328328
nodesNb +
329329
' nodes and ' +
@@ -389,7 +389,7 @@ describe('test performances', () => {
389389
}
390390
const dt = Date.now() - d;
391391

392-
console.log(
392+
console.info(
393393
'Time to create ' +
394394
(ID - nodeInti) +
395395
' nodes and ' +
@@ -408,15 +408,15 @@ describe('test performances', () => {
408408
memory.switchTo('1-2');
409409
memory.switchTo('1-3-1');
410410
const dt = Date.now() - d;
411-
console.log('Time to switch memory', dt);
411+
console.info('Time to switch memory', dt);
412412
expect(dt).to.lessThan(50);
413413
});
414414
it('Should read the nodes the first time in minimum time', () => {
415415
memory.switchTo('1-3-1');
416416
const d = Date.now();
417417
readAll(root);
418418
const dt = Date.now() - d;
419-
console.log('Time to load nodes', dt);
419+
console.info('Time to load nodes', dt);
420420
expect(dt).to.lessThan(250);
421421
});
422422
it('Should read the nodes in minimum time', () => {
@@ -426,15 +426,15 @@ describe('test performances', () => {
426426
const nodes = readAll(root);
427427
const dt = Date.now() - d;
428428
times.push(dt);
429-
console.log('Time to re-load nodes', dt);
429+
console.info('Time to re-load nodes', dt);
430430

431431
for (let k = 0; k < 5; k++) {
432432
const d = Date.now();
433433
// nodes.forEach(read);
434434
readAll(root);
435435
const dt = Date.now() - d;
436436
times.push(dt);
437-
console.log('Time to re-load nodes', dt);
437+
console.info('Time to re-load nodes', dt);
438438
}
439439

440440
let nodesNb = 0;
@@ -447,7 +447,7 @@ describe('test performances', () => {
447447
}
448448
});
449449
const average = Math.round(times.reduce((a, b) => a + b) / times.length);
450-
console.log(
450+
console.info(
451451
're-load ' + nodesNb + ' nodes and ' + chars + ' chars time average',
452452
average,
453453
);

packages/core/src/Memory/test/memory.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,19 @@ describe('core', () => {
118118
root['x+y'] = set;
119119
}).to.throw('other memory', 'set');
120120
});
121-
it('if try to makeVersionable on a versionable object', () => {
122-
const obj = new VersionableObject();
121+
it('if try to makeVersionable on a object already versionable with the old ref', () => {
122+
const obj = {};
123+
makeVersionable(obj);
123124
expect((): void => {
124125
makeVersionable(obj);
125126
}).to.throw('proxy', 'object');
126-
const array = new VersionableArray();
127+
const array = [];
128+
makeVersionable(array);
127129
expect((): void => {
128130
makeVersionable(array);
129131
}).to.throw('proxy', 'array');
130-
const set = new VersionableSet();
132+
const set = new Set();
133+
makeVersionable(set);
131134
expect((): void => {
132135
makeVersionable(set);
133136
}).to.throw('proxy', 'set');
@@ -853,7 +856,7 @@ describe('core', () => {
853856
expect(array.indexOf(-3)).to.equal(3);
854857
});
855858
it('array indexOf value several times', () => {
856-
const array = new VersionableArray(0, 1, 2, 3, 1, 4);
859+
const array = new VersionableArray<number>(0, 1, 2, 3, 1, 4);
857860
const memory = new Memory();
858861
memory.create('test');
859862
memory.switchTo('test');
@@ -1305,7 +1308,7 @@ describe('core', () => {
13051308
});
13061309
it('default value for array', () => {
13071310
const memory = new Memory();
1308-
const array = new VersionableArray(1, 2, 3, 4, 5);
1311+
const array = new VersionableArray<number>(1, 2, 3, 4, 5);
13091312
memory.linkToMemory(array);
13101313
memory.create('a');
13111314
memory.switchTo('a');
@@ -1321,7 +1324,7 @@ describe('core', () => {
13211324
memory.create('test');
13221325
memory.switchTo('test');
13231326

1324-
const array = new VersionableArray(1, 2, 3, 4, 5);
1327+
const array = new VersionableArray<number>(1, 2, 3, 4, 5);
13251328
memory.linkToMemory(array);
13261329
delete array[0];
13271330
array[0] = 1;
@@ -1335,7 +1338,7 @@ describe('core', () => {
13351338
memory.create('test');
13361339
memory.switchTo('test');
13371340

1338-
const array = new VersionableArray(1, 2, 3, 4, 5);
1341+
const array = new VersionableArray<number>(1, 2, 3, 4, 5);
13391342
memory.linkToMemory(array);
13401343

13411344
memory.create('1-1');
@@ -1359,7 +1362,7 @@ describe('core', () => {
13591362
});
13601363
it('array push and pop in same slide memory have a clean memory slice values', () => {
13611364
const memory = new Memory();
1362-
const array = new VersionableArray(1, 2, 3, 4, 5);
1365+
const array = new VersionableArray<number>(1, 2, 3, 4, 5);
13631366
memory.linkToMemory(array);
13641367
memory.create('1');
13651368
memory.switchTo('1');

packages/core/src/Modifier.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { Constructor } from '../../utils/src/utils';
22
import { VNode } from './VNodes/VNode';
3+
import { VersionableObject } from './Memory/VersionableObject';
34

45
interface ModifierConstructor {
56
new <T extends Constructor<Modifier>>(...args: ConstructorParameters<T>): this;
67
}
78
export interface Modifier {
89
constructor: ModifierConstructor & this;
910
}
10-
export class Modifier {
11+
export class Modifier extends VersionableObject {
1112
preserve = true;
1213
get name(): string {
1314
return '';

packages/core/src/Modifiers.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { Modifier } from './Modifier';
22
import { Constructor, isConstructor } from '../../utils/src/utils';
3+
import { VersionableObject } from './Memory/VersionableObject';
4+
import { VersionableArray } from './Memory/VersionableArray';
35

4-
export class Modifiers {
6+
export class Modifiers extends VersionableObject {
57
private _contents: Modifier[];
68
constructor(...modifiers: Array<Modifier | Constructor<Modifier>>) {
9+
super();
710
const clonedModifiers = modifiers.map(mod => {
811
return mod instanceof Modifier ? mod.clone() : mod;
912
});
@@ -49,7 +52,7 @@ export class Modifiers {
4952
*/
5053
append(...modifiers: Array<Modifier | Constructor<Modifier>>): void {
5154
if (modifiers.length && !this._contents) {
52-
this._contents = [];
55+
this._contents = new VersionableArray();
5356
}
5457
for (const modifier of modifiers) {
5558
if (modifier instanceof Modifier) {
@@ -67,7 +70,7 @@ export class Modifiers {
6770
*/
6871
prepend(...modifiers: Array<Modifier | Constructor<Modifier>>): void {
6972
if (modifiers.length && !this._contents) {
70-
this._contents = [];
73+
this._contents = new VersionableArray();
7174
}
7275
for (const modifier of [...modifiers].reverse()) {
7376
if (modifier instanceof Modifier) {

packages/core/src/VNodes/AbstractNode.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AtomicNode } from './AtomicNode';
55
import { Modifiers } from '../Modifiers';
66
import { EventMixin } from '../../../utils/src/EventMixin';
77
import { Modifier } from '../Modifier';
8+
import { markAsDiffRoot } from '../Memory/Memory';
89

910
export interface AbstractNodeParams {
1011
modifiers?: Modifiers | Array<Modifier | Constructor<Modifier>>;
@@ -40,6 +41,7 @@ export abstract class AbstractNode extends EventMixin {
4041
this.modifiers.append(...params.modifiers);
4142
}
4243
}
44+
markAsDiffRoot(this);
4345
}
4446

4547
get name(): string {

0 commit comments

Comments
 (0)