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

Commit 20be678

Browse files
committed
memory integration
1 parent b019461 commit 20be678

File tree

24 files changed

+150
-56
lines changed

24 files changed

+150
-56
lines changed

packages/core/src/Core.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class Core<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
8686
this.mode.is(range.startContainer, RuleProperty.EDITABLE)
8787
) {
8888
// Otherwise set range start at previous valid leaf.
89-
let ancestor = range.start.parent;
89+
let ancestor: VNode = range.start.parent;
9090
while (
9191
ancestor &&
9292
this.mode.is(ancestor, RuleProperty.BREAKABLE) &&
@@ -126,7 +126,7 @@ export class Core<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T>
126126
this.mode.is(range.endContainer, RuleProperty.EDITABLE)
127127
) {
128128
// Otherwise set range end at next valid leaf.
129-
let ancestor = range.end.parent;
129+
let ancestor: VNode = range.end.parent;
130130
while (
131131
ancestor &&
132132
this.mode.is(ancestor, RuleProperty.BREAKABLE) &&

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: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import { ContainerNode } from './VNodes/ContainerNode';
1010
import { AtomicNode } from './VNodes/AtomicNode';
1111
import { SeparatorNode } from './VNodes/SeparatorNode';
1212
import { ModeIdentifier, ModeDefinition, Mode } from './Mode';
13+
import { Memory } from './Memory/Memory';
14+
import { makeVersionable } from './Memory/Versionable';
15+
import { VersionableArray } from './Memory/VersionableArray';
1316

1417
export enum EditorStage {
1518
CONFIGURATION = 'configuration',
@@ -68,6 +71,9 @@ export class JWEditor {
6871
plugins: [],
6972
loadables: {},
7073
};
74+
memory: Memory;
75+
memoryID = 0;
76+
memoryInfo: { commandNames: string[] };
7177
selection = new VSelection(this);
7278
loaders: Record<string, Loader> = {};
7379
private mutex = Promise.resolve();
@@ -130,9 +136,18 @@ export class JWEditor {
130136
this.setMode(this.configuration.mode);
131137
}
132138

139+
// create memory
140+
this.memoryInfo = makeVersionable({ commandNames: [] });
141+
this.memory = new Memory();
142+
this.memory.linkToMemory(this.memoryInfo);
143+
133144
for (const plugin of this.plugins.values()) {
134145
await plugin.start();
135146
}
147+
148+
// create the next memory slice (and freeze the current memory)
149+
this.memoryID++;
150+
this.memory.create(this.memoryID.toString());
136151
}
137152

138153
//--------------------------------------------------------------------------
@@ -303,11 +318,16 @@ export class JWEditor {
303318
}
304319
}
305320

306-
async execBatch(callback: () => Promise<void>): Promise<void> {
307-
this.preventRenders.add(callback);
308-
await callback();
309-
this.preventRenders.delete(callback);
310-
await this.dispatcher.dispatchHooks('@batch');
321+
/**
322+
* Execute arbitrary code in `callback`, then dispatch the commit event.
323+
*
324+
* @param callback
325+
*/
326+
async execBatch(callback: () => Promise<void> | void): Promise<void> {
327+
return this._execBatchInMemory(() => {
328+
this.memoryInfo.commandNames.push('@batch');
329+
return callback();
330+
});
311331
}
312332

313333
/**
@@ -320,23 +340,49 @@ export class JWEditor {
320340
commandName: C,
321341
params?: CommandParams<P, C>,
322342
): Promise<void> {
323-
return await this.dispatcher.dispatch(commandName, params);
343+
await this._execBatchInMemory(() => {
344+
this.memoryInfo.commandNames.push(commandName);
345+
return this.dispatcher.dispatch(commandName, params);
346+
});
324347
}
325348

326349
/**
327-
* Execute arbitrary code in `callback`, then dispatch the event.
350+
* Execute arbitrary code in `callback` in a free memory slice.
351+
* Return true if we open a memory slice.
352+
*
353+
* TODO: create memory for each plugin who use the command then use
354+
* squashInto(winnerSliceKey, winnerSliceKey, newMasterSliceKey)
355+
*
356+
* @param callback
328357
*/
329-
async execCustomCommand<P extends JWPlugin, C extends Commands<P> = Commands<P>>(
330-
callback: () => Promise<void>,
331-
): Promise<void> {
358+
private async _execBatchInMemory(callback: () => Promise<void> | void): Promise<void> {
359+
const isFrozen = !this.memoryID || this.memory.isFrozen();
360+
if (isFrozen) {
361+
// Switch to the next memory slice (unfreeze the memory).
362+
this.memory.switchTo(this.memoryID.toString());
363+
this.memoryInfo.commandNames = new VersionableArray();
364+
}
332365
await callback();
333-
await this.dispatcher.dispatchHooks('@custom');
366+
if (isFrozen) {
367+
// Check if it's frozen for calling execCommand inside a call of
368+
// execCommand Create the next memory slice (and freeze the
369+
// current memory).
370+
this.memoryID++;
371+
this.memory.create(this.memoryID.toString());
372+
await this.dispatcher.commit();
373+
}
334374
}
335375

336376
/**
337377
* Stop this editor instance.
338378
*/
339379
async stop(): Promise<void> {
380+
if (this.memory) {
381+
// Unfreeze the memory.
382+
this.memory.create('stop');
383+
this.memory.switchTo('stop');
384+
this.memory = null;
385+
}
340386
for (const plugin of this.plugins.values()) {
341387
await plugin.stop();
342388
}

packages/core/src/Modifier.ts

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

45
export type ModifierTypeguard<T extends Modifier> = (
56
modifier: Modifier,
@@ -15,7 +16,7 @@ interface ModifierConstructor {
1516
export interface Modifier {
1617
constructor: ModifierConstructor & this;
1718
}
18-
export class Modifier {
19+
export class Modifier extends VersionableObject {
1920
preserve = true;
2021
get name(): string {
2122
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { AtomicNode } from './AtomicNode';
1010
import { Modifiers } from '../Modifiers';
1111
import { EventMixin } from '../../../utils/src/EventMixin';
1212
import { Modifier } from '../Modifier';
13+
import { markAsDiffRoot } from '../Memory/Memory';
1314

1415
export interface AbstractNodeParams {
1516
modifiers?: Modifiers | Array<Modifier | Constructor<Modifier>>;
@@ -71,6 +72,7 @@ export abstract class AbstractNode extends EventMixin {
7172
this.modifiers.append(...params.modifiers);
7273
}
7374
}
75+
markAsDiffRoot(this);
7476
}
7577

7678
get name(): string {
@@ -728,6 +730,7 @@ export abstract class AbstractNode extends EventMixin {
728730
return __repr;
729731
}
730732
}
733+
731734
export interface AbstractNode {
732735
constructor: new <T extends Constructor<VNode>>(...args: ConstructorParameters<T>) => this;
733736
}

packages/core/src/VNodes/ContainerNode.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { AbstractNode } from './AbstractNode';
22
import { VNode, Predicate, isLeaf } from './VNode';
33
import { ChildError } from '../../../utils/src/errors';
4+
import { VersionableArray } from '../Memory/VersionableArray';
45

56
export class ContainerNode extends AbstractNode {
67
parent: ContainerNode;
7-
readonly childVNodes: VNode[] = [];
8+
readonly childVNodes: VNode[] = new VersionableArray<VNode>();
89

910
//--------------------------------------------------------------------------
1011
// Browsing children.

packages/plugin-devtools/src/components/DevToolsComponent.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export class DevToolsComponent<T = {}> extends OwlComponent<T> {
3535
_heightOnLastMousedown: number;
3636

3737
async willStart(): Promise<void> {
38-
this.env.editor.dispatcher.registerCommandHook('*', this.refresh.bind(this));
38+
this.env.editor.dispatcher.registerCommandHook('*', this.addCommand.bind(this));
39+
this.env.editor.dispatcher.registerCommandHook('commit', this.render.bind(this));
3940
return super.willStart();
4041
}
4142
willUnmount(): void {
@@ -65,12 +66,10 @@ export class DevToolsComponent<T = {}> extends OwlComponent<T> {
6566
(this.inspectorRef.comp as InspectorComponent)?.inspectDom();
6667
}
6768
/**
68-
* Refresh this component with respect to the recent dispatching of the
69-
* given command with the given arguments.
69+
* Add the recent dispatching of the given command with the given arguments.
7070
*/
71-
refresh(params: CommandParams, id: CommandIdentifier): void {
71+
addCommand(params: CommandParams, id: CommandIdentifier): void {
7272
this.state.commands.push([id, params]);
73-
this.render();
7473
}
7574
/**
7675
* Drag the DevTools to resize them

packages/plugin-dialog/src/DialogZoneDomObjectRenderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class DialogZoneDomObjectRenderer extends NodeRenderer<DomObject> {
2424
async render(node: DialogZoneNode): Promise<DomObject> {
2525
const float = document.createElement('jw-dialog-container');
2626
for (const child of node.childVNodes) {
27-
if (!node.hidden.get(child) && (child.tangible || child.is(MetadataNode))) {
27+
if (!node.hidden?.[child.id] && (child.tangible || child.is(MetadataNode))) {
2828
float.appendChild(await this._renderDialog(child));
2929
}
3030
}

packages/plugin-dom-layout/src/DomLayout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPl
5353
domLocations: this._loadComponentLocations,
5454
};
5555
commandHooks = {
56-
'*': this.redraw,
56+
'commit': this._redraw,
5757
};
5858

5959
constructor(editor: JWEditor, configuration: T) {

0 commit comments

Comments
 (0)