diff --git a/src/app/store/initiable.ts b/src/app/store/initiable.ts new file mode 100644 index 0000000..f938e57 --- /dev/null +++ b/src/app/store/initiable.ts @@ -0,0 +1,6 @@ +export abstract class Initiable { + protected constructor() { + this.initiate(); + } + protected abstract initiate(); +} diff --git a/src/app/store/inner-node.ts b/src/app/store/inner-node.ts index 655ca69..6f37af8 100644 --- a/src/app/store/inner-node.ts +++ b/src/app/store/inner-node.ts @@ -1,11 +1,9 @@ import { Node } from './node'; -import { observableToBeFn } from 'rxjs/internal/testing/TestScheduler'; export abstract class InnerNode extends Node { - parent: Node; - nextVersion: this = null; - - protected readonly children: Array = []; + readonly children: Array = []; + protected parent: Node; + private nextVersion: this = null; get latestVersion(): this { let version; @@ -15,16 +13,6 @@ export abstract class InnerNode extends Node { return version; } - protected constructor(parent: Node) { - super(); - - new Promise(r => r()).then(() => - parent.addChild({ - value: this - }) - ); - } - mutatedUpdate() { this.parent.mutatedUpdate(); } @@ -33,30 +21,20 @@ export abstract class InnerNode extends Node { return this.update((self: this) => this.cloneWithMap.call(self, map)); } - changeKey({ propertyName, value }: { propertyName: string; value: any }): this { - return this.update((self: this) => this.cloneWithAdd.call(self, { propertyName, value })); - } - changeKeys(props: { [propertyName: string]: any }): this { return this.update((self: this) => this.cloneWithChangedKeys.call(self, props)); } - changeValue({ oldValue, newValue }: { oldValue: any; newValue: any }): this { - return this.update((self: this) => this.cloneWithModify.call(self, { oldValue, newValue })); - } - - addChild(update: { value: InnerNode }) { + addChild(update: { child: InnerNode }) { super.addChild.call(this.latestVersion, update); } changeChild(update: { oldValue: InnerNode; newValue: InnerNode }) { - super.changeChild.call(this.latestVersion, update); + super.replaceChild.call(this.latestVersion, update); } protected abstract cloneWithMap(map: (a: this) => void): this; - protected abstract cloneWithAdd(update: { value: any; propertyName: string }): this; protected abstract cloneWithChangedKeys(props: { [propertyName: string]: any }): this; - protected abstract cloneWithModify(update: { oldValue: any; newValue: any }): this; private update(cloneMethod: (self: this) => this): this { if (this.nextVersion !== null) { @@ -72,7 +50,7 @@ export abstract class InnerNode extends Node { child.parent = clone; } - this.parent.changeChild({ + this.parent.replaceChild({ oldValue: this, newValue: clone }); diff --git a/src/app/store/node.ts b/src/app/store/node.ts index c9d1384..1bee7cd 100644 --- a/src/app/store/node.ts +++ b/src/app/store/node.ts @@ -1,36 +1,32 @@ import { InnerNode } from './inner-node'; +import { Unique } from './unique'; -export abstract class Node { - protected static id = 0; - protected static sumCopyCount = 0; - protected abstract readonly children: Array; - private id = Node.id++; - protected copyCount = 1; - - abstract changeKey(update: { propertyName: string; value: any }); - abstract changeValue(update: { oldValue: any; newValue: any }); - - constructor() { - Node.sumCopyCount++; - } - +export abstract class Node extends Unique { + readonly children: Array; + // TODO: fix types. + protected abstract changeKeys(props: any): this; abstract mutatedUpdate(): void; - addChild(update: { value: InnerNode }) { - this.changeValue({ - oldValue: this.children, - newValue: [...this.children, update.value] + private copyCount = 0; + + protected initiate() { + super.initiate(); + this.copyCount++; + } + + addChild({ child }: { child: InnerNode }) { + this.changeKeys({ + children: [...this.children, child] }); } - changeChild({ oldValue, newValue }: { oldValue: InnerNode; newValue: InnerNode }) { + replaceChild({ oldValue, newValue }: { oldValue: InnerNode; newValue: InnerNode }) { if (oldValue === newValue) { return; } - this.changeValue({ - oldValue: this.children, - newValue: this.children.map(c => (c === oldValue ? newValue : c)) + this.changeKeys({ + children: this.children.map(c => (c === oldValue ? newValue : c)) }); } @@ -45,6 +41,6 @@ export abstract class Node { public log() { console.log(this._log()); - console.log(`All in all, there are ${Node.sumCopyCount} objects.`); + console.log(`All in all, there are ${Unique.ObjectCount} objects.`); } } diff --git a/src/app/store/unique.ts b/src/app/store/unique.ts new file mode 100644 index 0000000..a8228e4 --- /dev/null +++ b/src/app/store/unique.ts @@ -0,0 +1,17 @@ +import { Initiable } from './initiable'; + +export abstract class Unique extends Initiable { + protected static nextId = 0; + static get ObjectCount(): number { + return Unique.nextId; + } + + get id(): number { + return this._id; + } + private _id: number; + + protected initiate() { + this._id = Unique.nextId++; + } +}