reactronic 0.95.25040 → 0.95.25045
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -15
- package/build/dist/source/core/Changeset.d.ts +2 -2
- package/build/dist/source/core/Changeset.js +2 -2
- package/build/dist/source/core/Data.d.ts +3 -3
- package/build/dist/source/core/Mvcc.js +2 -4
- package/build/dist/source/core/Operation.d.ts +8 -8
- package/build/dist/source/core/Operation.js +36 -36
- package/build/dist/source/core/Transaction.js +33 -33
- package/build/dist/source/core/TreeNode.js +1 -1
- package/build/dist/source/util/LinkedList.d.ts +21 -1
- package/build/dist/source/util/LinkedList.js +139 -4
- package/package.json +1 -1
- package/build/dist/source/util/LinkedListRenovation.d.ts +0 -20
- package/build/dist/source/util/LinkedListRenovation.js +0 -134
package/README.md
CHANGED
|
@@ -187,8 +187,8 @@ in response to changes in signalling objects made by
|
|
|
187
187
|
transactional functions. Cached function is called on-demand
|
|
188
188
|
to renew the result if it was marked as obsolete due to
|
|
189
189
|
changes made by an transactional functions. Reactive and cached
|
|
190
|
-
functions are instrumented with hooks to
|
|
191
|
-
|
|
190
|
+
functions are instrumented with hooks to seamless
|
|
191
|
+
listening of those signalling objects and other cached
|
|
192
192
|
functions (dependencies), which are used during their
|
|
193
193
|
execution.
|
|
194
194
|
|
|
@@ -202,7 +202,7 @@ class MyView extends Component<{model: MyModel}> {
|
|
|
202
202
|
<div>{this.props.model.content}</div>
|
|
203
203
|
</div>
|
|
204
204
|
)
|
|
205
|
-
} // render is
|
|
205
|
+
} // render is listening to "url" and "content"
|
|
206
206
|
}
|
|
207
207
|
```
|
|
208
208
|
|
|
@@ -219,15 +219,15 @@ class Component<P> extends React.Component<P> {
|
|
|
219
219
|
// Ask React to re-render
|
|
220
220
|
Transaction.outside(() => this.setState({}))
|
|
221
221
|
}
|
|
222
|
-
} // EnsureUpToDate is
|
|
222
|
+
} // EnsureUpToDate is listening to render
|
|
223
223
|
|
|
224
224
|
shouldComponentUpdate(): boolean {
|
|
225
|
-
const r =
|
|
225
|
+
const r = manageReaction(this.render)
|
|
226
226
|
return !r.isUpToDate
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
componentDidMount(): void {
|
|
230
|
-
// Run
|
|
230
|
+
// Run for the first time to start listening
|
|
231
231
|
this.ensureUpToDate()
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -237,9 +237,9 @@ class Component<P> extends React.Component<P> {
|
|
|
237
237
|
}
|
|
238
238
|
```
|
|
239
239
|
|
|
240
|
-
In the example above, reactive function `refresh`
|
|
241
|
-
transparently
|
|
242
|
-
In turn, cached function `render`
|
|
240
|
+
In the example above, reactive function `refresh`
|
|
241
|
+
transparently listens to the cached function `render`.
|
|
242
|
+
In turn, cached function `render` listens to the
|
|
243
243
|
properties `url` and `content` of a corresponding `MyModel`
|
|
244
244
|
object. Once `url` or `content` values are changed, the
|
|
245
245
|
cached function `render` becomes obsolete and causes the
|
|
@@ -260,7 +260,7 @@ reactive functions) or on-demand (for cached functions).
|
|
|
260
260
|
Reactronic takes full care of tracking dependencies
|
|
261
261
|
between all the signalling objects and reactive/cached
|
|
262
262
|
functions. With Reactronic, you no longer need to create
|
|
263
|
-
data change events in one set of objects,
|
|
263
|
+
data change events in one set of objects, listen to
|
|
264
264
|
these events in other objects, and manually maintain
|
|
265
265
|
switching from the previous object version to a new one.
|
|
266
266
|
|
|
@@ -324,8 +324,8 @@ NPM: `npm install reactronic`
|
|
|
324
324
|
|
|
325
325
|
// Classes
|
|
326
326
|
|
|
327
|
-
class
|
|
328
|
-
class
|
|
327
|
+
class TxObject { } // transactional object
|
|
328
|
+
class SxObject { } // signalling object
|
|
329
329
|
|
|
330
330
|
// Decorators & Operators
|
|
331
331
|
|
|
@@ -447,9 +447,9 @@ class Transaction implements Worker {
|
|
|
447
447
|
static isCanceled: boolean
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
-
//
|
|
450
|
+
// Reaction
|
|
451
451
|
|
|
452
|
-
abstract class
|
|
452
|
+
abstract class Reaction<T> {
|
|
453
453
|
readonly options: Options
|
|
454
454
|
readonly args: ReadonlyArray<any>
|
|
455
455
|
readonly value: T
|
|
@@ -467,7 +467,7 @@ abstract class Operation<T> {
|
|
|
467
467
|
class ReactiveSystem {
|
|
468
468
|
static why(short: boolean = false): string
|
|
469
469
|
static getMethodCache<T>(method: F<T>): Cache<T>
|
|
470
|
-
static
|
|
470
|
+
static configureCurrentReaction(options: Partial<Options>): Options
|
|
471
471
|
static getRevisionOf(obj: any): number
|
|
472
472
|
static takeSnapshot<T>(obj: T): T
|
|
473
473
|
static dispose(obj: any): void
|
|
@@ -31,8 +31,8 @@ export declare class Changeset implements AbstractChangeset {
|
|
|
31
31
|
isResolved: boolean;
|
|
32
32
|
resolvedValue: any;
|
|
33
33
|
};
|
|
34
|
-
static
|
|
35
|
-
static
|
|
34
|
+
static propagateAllChangesToListeners: (changeset: Changeset) => void;
|
|
35
|
+
static discardAllListeners: (changeset: Changeset) => void;
|
|
36
36
|
static enqueueReactionsToRun: (reactions: Array<OperationFootprint>) => void;
|
|
37
37
|
lookupObjectVersion(h: ObjectHandle, fk: FieldKey, editing: boolean): ObjectVersion;
|
|
38
38
|
getObjectVersion(h: ObjectHandle, fk: FieldKey): ObjectVersion;
|
|
@@ -316,8 +316,8 @@ Changeset.edit = UNDEF;
|
|
|
316
316
|
Changeset.markUsed = UNDEF;
|
|
317
317
|
Changeset.markEdited = UNDEF;
|
|
318
318
|
Changeset.tryResolveConflict = UNDEF;
|
|
319
|
-
Changeset.
|
|
320
|
-
Changeset.
|
|
319
|
+
Changeset.propagateAllChangesToListeners = (changeset) => { };
|
|
320
|
+
Changeset.discardAllListeners = (changeset) => { };
|
|
321
321
|
Changeset.enqueueReactionsToRun = (reactions) => { };
|
|
322
322
|
export class Dump {
|
|
323
323
|
static obj(h, fk, stamp, changesetId, lastEditorChangesetId, value) {
|
|
@@ -7,21 +7,21 @@ export type AbstractChangeset = {
|
|
|
7
7
|
};
|
|
8
8
|
export declare class ContentFootprint<T = any> {
|
|
9
9
|
content: T;
|
|
10
|
-
|
|
10
|
+
listeners?: Set<OperationFootprint>;
|
|
11
11
|
lastEditorChangesetId: number;
|
|
12
12
|
get isComputed(): boolean;
|
|
13
13
|
constructor(content: T, lastEditorChangesetId: number);
|
|
14
14
|
}
|
|
15
15
|
export type OperationFootprint = {
|
|
16
16
|
readonly order: number;
|
|
17
|
-
readonly signals: Map<ContentFootprint,
|
|
17
|
+
readonly signals: Map<ContentFootprint, ListeningInfo> | undefined;
|
|
18
18
|
readonly obsoleteSince: number;
|
|
19
19
|
hint(nop?: boolean): string;
|
|
20
20
|
markObsoleteDueTo(footprint: ContentFootprint, fk: FieldKey, changeset: AbstractChangeset, h: ObjectHandle, outer: string, since: number, collector: Array<OperationFootprint>): void;
|
|
21
21
|
relaunchIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
22
22
|
};
|
|
23
23
|
export type FieldKey = PropertyKey;
|
|
24
|
-
export type
|
|
24
|
+
export type ListeningInfo = {
|
|
25
25
|
readonly memberHint: string;
|
|
26
26
|
readonly usageCount: number;
|
|
27
27
|
};
|
|
@@ -100,10 +100,8 @@ export class Mvcc {
|
|
|
100
100
|
return fk in ov.data || fk in h.data;
|
|
101
101
|
}
|
|
102
102
|
defineProperty(h, name, attributes) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
Object.defineProperty(h.data, name, attributes);
|
|
106
|
-
return result;
|
|
103
|
+
Object.defineProperty(h.data, name, attributes);
|
|
104
|
+
return true;
|
|
107
105
|
}
|
|
108
106
|
getOwnPropertyDescriptor(h, fk) {
|
|
109
107
|
const ov = Changeset.current().getObjectVersion(h, fk);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { F } from "../util/Utils.js";
|
|
2
2
|
import { Reaction, ReactivityOptions } from "../Options.js";
|
|
3
|
-
import { FieldKey, ObjectHandle, ContentFootprint, OperationFootprint,
|
|
3
|
+
import { FieldKey, ObjectHandle, ContentFootprint, OperationFootprint, ListeningInfo, AbstractChangeset } from "./Data.js";
|
|
4
4
|
import { Transaction } from "./Transaction.js";
|
|
5
5
|
import { OptionsImpl } from "./Mvcc.js";
|
|
6
6
|
export declare class ReactionImpl implements Reaction<any> {
|
|
@@ -39,7 +39,7 @@ declare class OperationFootprintImpl extends ContentFootprint implements Operati
|
|
|
39
39
|
readonly transaction: Transaction;
|
|
40
40
|
readonly descriptor: ReactionImpl;
|
|
41
41
|
readonly changeset: AbstractChangeset;
|
|
42
|
-
signals: Map<ContentFootprint,
|
|
42
|
+
signals: Map<ContentFootprint, ListeningInfo> | undefined;
|
|
43
43
|
options: OptionsImpl;
|
|
44
44
|
cause: string | undefined;
|
|
45
45
|
args: any[];
|
|
@@ -75,15 +75,15 @@ declare class OperationFootprintImpl extends ContentFootprint implements Operati
|
|
|
75
75
|
private static markUsed;
|
|
76
76
|
private static markEdited;
|
|
77
77
|
private static tryResolveConflict;
|
|
78
|
-
private static
|
|
79
|
-
private static
|
|
80
|
-
private static
|
|
78
|
+
private static propagateAllChangesToListeners;
|
|
79
|
+
private static discardAllListeners;
|
|
80
|
+
private static propagateFieldChangeToListeners;
|
|
81
81
|
private static enqueueReactionsToRun;
|
|
82
82
|
private static migrateContentFootprint;
|
|
83
83
|
private static processQueuedReactions;
|
|
84
|
-
private
|
|
85
|
-
private
|
|
86
|
-
private static
|
|
84
|
+
private stopListeningAllSignals;
|
|
85
|
+
private listenTo;
|
|
86
|
+
private static canListenTo;
|
|
87
87
|
private static createOperationDescriptor;
|
|
88
88
|
private static rememberOperationOptions;
|
|
89
89
|
static init(): void;
|
|
@@ -301,11 +301,11 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
301
301
|
Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", isReactive ? "█" : "▒", isReactive && changeset === EMPTY_OBJECT_VERSION.changeset
|
|
302
302
|
? `${this.hint()} is reactive and will run automatically (order ${this.options.order})`
|
|
303
303
|
: `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, fk)} since s${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ""}`);
|
|
304
|
-
this.
|
|
304
|
+
this.stopListeningAllSignals();
|
|
305
305
|
if (isReactive)
|
|
306
306
|
collector.push(this);
|
|
307
307
|
else
|
|
308
|
-
(_b = this.
|
|
308
|
+
(_b = this.listeners) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.descriptor.fieldKey, this.changeset, this.descriptor.ownerHandle, why, since, collector));
|
|
309
309
|
const tran = this.transaction;
|
|
310
310
|
if (tran.changeset === changeset) {
|
|
311
311
|
}
|
|
@@ -470,15 +470,15 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
470
470
|
}
|
|
471
471
|
static markUsed(footprint, ov, fk, h, kind, weak) {
|
|
472
472
|
if (kind !== Kind.transaction) {
|
|
473
|
-
const
|
|
474
|
-
if (
|
|
475
|
-
|
|
473
|
+
const listener = OperationFootprintImpl.current;
|
|
474
|
+
if (listener && listener.options.kind !== Kind.transaction &&
|
|
475
|
+
listener.transaction === Transaction.current && fk !== Meta.Handle) {
|
|
476
476
|
const ctx = Changeset.current();
|
|
477
477
|
if (ctx !== ov.changeset)
|
|
478
478
|
ctx.bumpBy(ov.changeset.timestamp);
|
|
479
479
|
const t = weak ? -1 : ctx.timestamp;
|
|
480
|
-
if (!
|
|
481
|
-
|
|
480
|
+
if (!listener.listenTo(footprint, ov, fk, h, t))
|
|
481
|
+
listener.markObsoleteDueTo(footprint, fk, h.applied.changeset, h, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
484
|
}
|
|
@@ -502,28 +502,28 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
502
502
|
}
|
|
503
503
|
return { isResolved, resolvedValue };
|
|
504
504
|
}
|
|
505
|
-
static
|
|
505
|
+
static propagateAllChangesToListeners(changeset) {
|
|
506
506
|
var _a;
|
|
507
507
|
const since = changeset.timestamp;
|
|
508
508
|
const obsolete = changeset.obsolete;
|
|
509
509
|
changeset.items.forEach((ov, h) => {
|
|
510
|
-
OperationFootprintImpl.
|
|
510
|
+
OperationFootprintImpl.propagateFieldChangeToListeners(false, since, ov, Meta.Revision, h, obsolete);
|
|
511
511
|
if (!ov.disposed)
|
|
512
|
-
ov.changes.forEach((o, fk) => OperationFootprintImpl.
|
|
512
|
+
ov.changes.forEach((o, fk) => OperationFootprintImpl.propagateFieldChangeToListeners(false, since, ov, fk, h, obsolete));
|
|
513
513
|
else
|
|
514
514
|
for (const fk in ov.former.objectVersion.data)
|
|
515
|
-
OperationFootprintImpl.
|
|
515
|
+
OperationFootprintImpl.propagateFieldChangeToListeners(true, since, ov, fk, h, obsolete);
|
|
516
516
|
});
|
|
517
517
|
obsolete.sort(compareReactionsByOrder);
|
|
518
518
|
(_a = changeset.options.journal) === null || _a === void 0 ? void 0 : _a.edited(JournalImpl.buildPatch(changeset.hint, changeset.items));
|
|
519
519
|
}
|
|
520
|
-
static
|
|
520
|
+
static discardAllListeners(changeset) {
|
|
521
521
|
changeset.items.forEach((ov, h) => {
|
|
522
|
-
OperationFootprintImpl.
|
|
523
|
-
ov.changes.forEach((o, fk) => OperationFootprintImpl.
|
|
522
|
+
OperationFootprintImpl.propagateFieldChangeToListeners(true, changeset.timestamp, ov, Meta.Revision, h, undefined);
|
|
523
|
+
ov.changes.forEach((o, fk) => OperationFootprintImpl.propagateFieldChangeToListeners(true, changeset.timestamp, ov, fk, h, undefined));
|
|
524
524
|
});
|
|
525
525
|
}
|
|
526
|
-
static
|
|
526
|
+
static propagateFieldChangeToListeners(stopListening, timestamp, ov, fk, h, collector) {
|
|
527
527
|
var _a;
|
|
528
528
|
const curr = ov.data[fk];
|
|
529
529
|
if (collector !== undefined) {
|
|
@@ -534,7 +534,7 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
534
534
|
if ((former.obsoleteSince === MAX_REVISION || former.obsoleteSince <= 0)) {
|
|
535
535
|
former.obsoleteDueTo = why;
|
|
536
536
|
former.obsoleteSince = timestamp;
|
|
537
|
-
former.
|
|
537
|
+
former.stopListeningAllSignals();
|
|
538
538
|
}
|
|
539
539
|
const formerSuccessor = former.successor;
|
|
540
540
|
if (formerSuccessor !== curr) {
|
|
@@ -544,7 +544,7 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
544
544
|
else
|
|
545
545
|
former.successor = undefined;
|
|
546
546
|
}
|
|
547
|
-
(_a = former.
|
|
547
|
+
(_a = former.listeners) === null || _a === void 0 ? void 0 : _a.forEach(s => {
|
|
548
548
|
const t = s.transaction;
|
|
549
549
|
const o = t.isFinished ? collector : t.changeset.obsolete;
|
|
550
550
|
return s.markObsoleteDueTo(former, fk, ov.changeset, h, why, timestamp, o);
|
|
@@ -559,11 +559,11 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
559
559
|
Log.write("", "[!]", `${curr.hint()} uses ${info.memberHint} ${info.usageCount} times (consider remembering it in a local variable)`, 0, " *** WARNING ***");
|
|
560
560
|
});
|
|
561
561
|
}
|
|
562
|
-
if (
|
|
563
|
-
curr.
|
|
562
|
+
if (stopListening)
|
|
563
|
+
curr.stopListeningAllSignals();
|
|
564
564
|
}
|
|
565
565
|
}
|
|
566
|
-
else if (curr instanceof ContentFootprint && curr.
|
|
566
|
+
else if (curr instanceof ContentFootprint && curr.listeners) {
|
|
567
567
|
}
|
|
568
568
|
}
|
|
569
569
|
static enqueueReactionsToRun(reactions) {
|
|
@@ -592,20 +592,20 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
592
592
|
}
|
|
593
593
|
OperationFootprintImpl.queuedReactions = [];
|
|
594
594
|
}
|
|
595
|
-
|
|
595
|
+
stopListeningAllSignals() {
|
|
596
596
|
var _a;
|
|
597
597
|
(_a = this.signals) === null || _a === void 0 ? void 0 : _a.forEach((info, value) => {
|
|
598
598
|
var _a;
|
|
599
|
-
value.
|
|
599
|
+
value.listeners.delete(this);
|
|
600
600
|
if (Log.isOn && (Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
|
|
601
|
-
Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", "-", `${this.hint()} is
|
|
601
|
+
Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", "-", `${this.hint()} is no longer listening to ${info.memberHint}`);
|
|
602
602
|
});
|
|
603
603
|
this.signals = undefined;
|
|
604
604
|
}
|
|
605
|
-
|
|
605
|
+
listenTo(footprint, ov, fk, h, timestamp) {
|
|
606
606
|
var _a, _b, _c;
|
|
607
607
|
const parent = this.transaction.changeset.parent;
|
|
608
|
-
const ok = OperationFootprintImpl.
|
|
608
|
+
const ok = OperationFootprintImpl.canListenTo(footprint, ov, parent, fk, h, timestamp);
|
|
609
609
|
if (ok) {
|
|
610
610
|
let times = 0;
|
|
611
611
|
if (Mvcc.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
|
|
@@ -613,24 +613,24 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
613
613
|
times = existing ? existing.usageCount + 1 : 1;
|
|
614
614
|
}
|
|
615
615
|
if (this.signals !== undefined) {
|
|
616
|
-
if (!footprint.
|
|
617
|
-
footprint.
|
|
618
|
-
const
|
|
619
|
-
footprint.
|
|
620
|
-
this.signals.set(footprint,
|
|
616
|
+
if (!footprint.listeners)
|
|
617
|
+
footprint.listeners = new Set();
|
|
618
|
+
const listening = { memberHint: Dump.snapshot2(h, ov.changeset, fk), usageCount: times };
|
|
619
|
+
footprint.listeners.add(this);
|
|
620
|
+
this.signals.set(footprint, listening);
|
|
621
621
|
if (Log.isOn && (Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
|
|
622
|
-
Log.write("║", " ∞", `${this.hint()}
|
|
622
|
+
Log.write("║", " ∞", `${this.hint()} now listens to ${Dump.snapshot2(h, ov.changeset, fk, footprint)}${listening.usageCount > 1 ? ` (${listening.usageCount} times)` : ""}`);
|
|
623
623
|
}
|
|
624
624
|
else if (Log.isOn && (Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
|
|
625
|
-
Log.write("║", " x", `${this.hint()} is obsolete and is
|
|
625
|
+
Log.write("║", " x", `${this.hint()} is obsolete and is not listening to ${Dump.snapshot2(h, ov.changeset, fk, footprint)}`);
|
|
626
626
|
}
|
|
627
627
|
else {
|
|
628
628
|
if (Log.isOn && (Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
|
|
629
|
-
Log.write("║", " x", `${this.hint()} is
|
|
629
|
+
Log.write("║", " x", `${this.hint()} is not listening to already obsolete ${Dump.snapshot2(h, ov.changeset, fk, footprint)}`);
|
|
630
630
|
}
|
|
631
631
|
return ok;
|
|
632
632
|
}
|
|
633
|
-
static
|
|
633
|
+
static canListenTo(footprint, ov, parent, fk, h, timestamp) {
|
|
634
634
|
const parentSnapshot = parent ? parent.lookupObjectVersion(h, fk, false) : h.applied;
|
|
635
635
|
const parentFootprint = parentSnapshot.data[fk];
|
|
636
636
|
let result = footprint === parentFootprint || (!ov.changeset.sealed && ov.former.objectVersion.data[fk] === parentFootprint);
|
|
@@ -669,8 +669,8 @@ class OperationFootprintImpl extends ContentFootprint {
|
|
|
669
669
|
Changeset.markUsed = OperationFootprintImpl.markUsed;
|
|
670
670
|
Changeset.markEdited = OperationFootprintImpl.markEdited;
|
|
671
671
|
Changeset.tryResolveConflict = OperationFootprintImpl.tryResolveConflict;
|
|
672
|
-
Changeset.
|
|
673
|
-
Changeset.
|
|
672
|
+
Changeset.propagateAllChangesToListeners = OperationFootprintImpl.propagateAllChangesToListeners;
|
|
673
|
+
Changeset.discardAllListeners = OperationFootprintImpl.discardAllListeners;
|
|
674
674
|
Changeset.enqueueReactionsToRun = OperationFootprintImpl.enqueueReactionsToRun;
|
|
675
675
|
TransactionImpl.migrateContentFootprint = OperationFootprintImpl.migrateContentFootprint;
|
|
676
676
|
Mvcc.createOperationDescriptor = OperationFootprintImpl.createOperationDescriptor;
|
|
@@ -258,7 +258,7 @@ export class TransactionImpl extends Transaction {
|
|
|
258
258
|
if (after && after !== TransactionImpl.none)
|
|
259
259
|
Log.write("║", " [!]", `T${t.id}[${t.hint}] will be restarted${t !== after ? ` after T${after.id}[${after.hint}]` : ""}`);
|
|
260
260
|
}
|
|
261
|
-
Changeset.
|
|
261
|
+
Changeset.discardAllListeners(t.changeset);
|
|
262
262
|
}
|
|
263
263
|
t.sealed = true;
|
|
264
264
|
}
|
|
@@ -328,7 +328,7 @@ export class TransactionImpl extends Transaction {
|
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
330
|
else if (!error)
|
|
331
|
-
Changeset.
|
|
331
|
+
Changeset.propagateAllChangesToListeners(changeset);
|
|
332
332
|
return obsolete;
|
|
333
333
|
}
|
|
334
334
|
applyObjectChanges(h, ov) {
|
|
@@ -359,39 +359,39 @@ export class TransactionImpl extends Transaction {
|
|
|
359
359
|
if (cf.isComputed) {
|
|
360
360
|
const migrated = TransactionImpl.migrateContentFootprint(cf, tParent);
|
|
361
361
|
if (ovParent.former.objectVersion.data[fk] !== cfParent) {
|
|
362
|
-
let
|
|
363
|
-
if (
|
|
364
|
-
const
|
|
365
|
-
|
|
362
|
+
let listeners = cfParent.listeners;
|
|
363
|
+
if (listeners) {
|
|
364
|
+
const migratedListeners = migrated.listeners = new Set();
|
|
365
|
+
listeners.forEach(o => {
|
|
366
366
|
const conformingSignals = o.signals;
|
|
367
367
|
const sub = conformingSignals.get(cfParent);
|
|
368
368
|
conformingSignals.delete(cfParent);
|
|
369
369
|
conformingSignals.set(migrated, sub);
|
|
370
|
-
|
|
370
|
+
migratedListeners.add(o);
|
|
371
371
|
});
|
|
372
|
-
cfParent.
|
|
372
|
+
cfParent.listeners = undefined;
|
|
373
373
|
}
|
|
374
|
-
|
|
375
|
-
if (
|
|
376
|
-
let
|
|
377
|
-
if (
|
|
378
|
-
|
|
379
|
-
|
|
374
|
+
listeners = cf.listeners;
|
|
375
|
+
if (listeners) {
|
|
376
|
+
let migratedListeners = migrated.listeners;
|
|
377
|
+
if (migratedListeners === undefined)
|
|
378
|
+
migratedListeners = migrated.listeners = new Set();
|
|
379
|
+
listeners.forEach(o => {
|
|
380
380
|
const conformingSignals = o.signals;
|
|
381
381
|
const sub = conformingSignals.get(cf);
|
|
382
382
|
conformingSignals.delete(cf);
|
|
383
383
|
conformingSignals.set(migrated, sub);
|
|
384
|
-
|
|
384
|
+
migratedListeners.add(o);
|
|
385
385
|
});
|
|
386
|
-
cf.
|
|
386
|
+
cf.listeners = undefined;
|
|
387
387
|
}
|
|
388
388
|
const signals = cf.signals;
|
|
389
389
|
const migratedSignals = migrated.signals;
|
|
390
390
|
if (signals) {
|
|
391
391
|
signals.forEach((s, o) => {
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
392
|
+
const conformingListeners = o.listeners;
|
|
393
|
+
conformingListeners.delete(cf);
|
|
394
|
+
conformingListeners.add(migrated);
|
|
395
395
|
migratedSignals.set(o, s);
|
|
396
396
|
});
|
|
397
397
|
signals.clear();
|
|
@@ -399,25 +399,25 @@ export class TransactionImpl extends Transaction {
|
|
|
399
399
|
ovParent.data[fk] = migrated;
|
|
400
400
|
}
|
|
401
401
|
else {
|
|
402
|
-
const
|
|
403
|
-
if (
|
|
404
|
-
const migratedReactions = migrated.
|
|
405
|
-
|
|
402
|
+
const listeners = cf.listeners;
|
|
403
|
+
if (listeners) {
|
|
404
|
+
const migratedReactions = migrated.listeners = new Set();
|
|
405
|
+
listeners.forEach(o => {
|
|
406
406
|
const conformingSignals = o.signals;
|
|
407
407
|
const sub = conformingSignals.get(cf);
|
|
408
408
|
conformingSignals.delete(cf);
|
|
409
409
|
conformingSignals.set(migrated, sub);
|
|
410
410
|
migratedReactions.add(o);
|
|
411
411
|
});
|
|
412
|
-
cf.
|
|
412
|
+
cf.listeners = undefined;
|
|
413
413
|
}
|
|
414
414
|
const signals = cf.signals;
|
|
415
415
|
const migratedSignals = migrated.signals;
|
|
416
416
|
if (signals) {
|
|
417
417
|
signals.forEach((s, o) => {
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
418
|
+
const conformingListeners = o.listeners;
|
|
419
|
+
conformingListeners.delete(cf);
|
|
420
|
+
conformingListeners.add(migrated);
|
|
421
421
|
migratedSignals.set(o, s);
|
|
422
422
|
});
|
|
423
423
|
signals.clear();
|
|
@@ -431,16 +431,16 @@ export class TransactionImpl extends Transaction {
|
|
|
431
431
|
const parentContent = cfParent === null || cfParent === void 0 ? void 0 : cfParent.content;
|
|
432
432
|
if (ovParent.former.objectVersion.data[fk] !== cfParent) {
|
|
433
433
|
cfParent.content = cf.content;
|
|
434
|
-
const
|
|
435
|
-
if (
|
|
436
|
-
if (cfParent.
|
|
437
|
-
cfParent.
|
|
438
|
-
|
|
434
|
+
const listeners = cf.listeners;
|
|
435
|
+
if (listeners) {
|
|
436
|
+
if (cfParent.listeners === undefined)
|
|
437
|
+
cfParent.listeners = new Set();
|
|
438
|
+
listeners.forEach(o => {
|
|
439
439
|
const conformingSignals = o.signals;
|
|
440
440
|
const sub = conformingSignals.get(cf);
|
|
441
441
|
conformingSignals.delete(cf);
|
|
442
442
|
conformingSignals.set(cfParent, sub);
|
|
443
|
-
cfParent.
|
|
443
|
+
cfParent.listeners.add(o);
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
446
|
}
|
|
@@ -23,7 +23,7 @@ import { emitLetters, flags, getCallerInfo, proceedSyncOrAsync } from "../util/U
|
|
|
23
23
|
import { Priority, Mode, Isolation, Reentrance } from "../Enums.js";
|
|
24
24
|
import { SxObject } from "../core/Mvcc.js";
|
|
25
25
|
import { Transaction } from "../core/Transaction.js";
|
|
26
|
-
import { ReactiveSystem, options, signal, reaction, runTransactional, runNonReactive, manageReaction, disposeSignallingObject
|
|
26
|
+
import { ReactiveSystem, options, signal, reaction, runTransactional, runNonReactive, manageReaction, disposeSignallingObject } from "../System.js";
|
|
27
27
|
export function declare(driver, scriptOrDeclaration, scriptAsync, key, mode, preparation, preparationAsync, finalization, triggers, basis) {
|
|
28
28
|
let result;
|
|
29
29
|
let declaration;
|
|
@@ -5,7 +5,7 @@ export declare class LinkedList<T extends LinkedItem<T>> {
|
|
|
5
5
|
private isStrictOrder$;
|
|
6
6
|
private map;
|
|
7
7
|
items$: LinkedSubList<T>;
|
|
8
|
-
|
|
8
|
+
private renovation;
|
|
9
9
|
constructor(keyExtractor: KeyExtractor<T>, isStrictOrder?: boolean);
|
|
10
10
|
get isStrictOrder(): boolean;
|
|
11
11
|
set isStrictOrder(value: boolean);
|
|
@@ -16,6 +16,8 @@ export declare class LinkedList<T extends LinkedItem<T>> {
|
|
|
16
16
|
add(item: T, before?: T): void;
|
|
17
17
|
move(item: T, before: T | undefined): void;
|
|
18
18
|
remove(item: T): void;
|
|
19
|
+
beginRenovation(diff?: Array<T>): LinkedListRenovation<T>;
|
|
20
|
+
endRenovation(error?: unknown): void;
|
|
19
21
|
static move$<T extends LinkedItem<T>>(list: LinkedList<T>, item: T, before: T | undefined): void;
|
|
20
22
|
static remove$<T extends LinkedItem<T>>(list: LinkedList<T>, item: T): void;
|
|
21
23
|
static removeKey$<T extends LinkedItem<T>>(list: LinkedList<T>, key: string | undefined): void;
|
|
@@ -50,3 +52,21 @@ export declare class LinkedSubList<T extends LinkedItem<T>> {
|
|
|
50
52
|
clear(): void;
|
|
51
53
|
grab(from: LinkedSubList<T>, join: boolean): void;
|
|
52
54
|
}
|
|
55
|
+
export declare class LinkedListRenovation<T extends LinkedItem<T>> {
|
|
56
|
+
readonly list: LinkedList<T>;
|
|
57
|
+
readonly diff: Array<T> | undefined;
|
|
58
|
+
private former;
|
|
59
|
+
private expected;
|
|
60
|
+
private absent;
|
|
61
|
+
constructor(list: LinkedList<T>, former: LinkedSubList<T>, diff?: Array<T>);
|
|
62
|
+
lookup(key: string | undefined): T | undefined;
|
|
63
|
+
tryToProlong(key: string, resolution?: {
|
|
64
|
+
isDuplicate: boolean;
|
|
65
|
+
}, error?: string): T | undefined;
|
|
66
|
+
thisIsAdded(item: T, before?: T): T;
|
|
67
|
+
thisIsModified(item: T): void;
|
|
68
|
+
thisIsMoved(item: T, before: T | undefined): void;
|
|
69
|
+
thisIsRemoved(item: T): void;
|
|
70
|
+
get lostItemCount(): number;
|
|
71
|
+
lostItems(): Generator<T>;
|
|
72
|
+
}
|
|
@@ -5,20 +5,20 @@ export class LinkedList {
|
|
|
5
5
|
this.isStrictOrder$ = isStrictOrder;
|
|
6
6
|
this.map = new Map();
|
|
7
7
|
this.items$ = new LinkedSubList();
|
|
8
|
-
this.
|
|
8
|
+
this.renovation = undefined;
|
|
9
9
|
}
|
|
10
10
|
get isStrictOrder() { return this.isStrictOrder$; }
|
|
11
11
|
set isStrictOrder(value) {
|
|
12
|
-
if (this.
|
|
12
|
+
if (this.renovation !== undefined)
|
|
13
13
|
throw misuse("cannot change strict mode in the middle of renovation");
|
|
14
14
|
this.isStrictOrder$ = value;
|
|
15
15
|
}
|
|
16
16
|
get isRenovationInProgress() {
|
|
17
|
-
return this.
|
|
17
|
+
return this.renovation !== undefined;
|
|
18
18
|
}
|
|
19
19
|
get count() {
|
|
20
20
|
var _a, _b;
|
|
21
|
-
return this.items$.count + ((_b = (_a = this.
|
|
21
|
+
return this.items$.count + ((_b = (_a = this.renovation) === null || _a === void 0 ? void 0 : _a.lostItemCount) !== null && _b !== void 0 ? _b : 0);
|
|
22
22
|
}
|
|
23
23
|
items() {
|
|
24
24
|
return this.items$.items();
|
|
@@ -47,6 +47,38 @@ export class LinkedList {
|
|
|
47
47
|
throw misuse("cannot remove given item outside of renovation cycle");
|
|
48
48
|
LinkedList.remove$(this, item);
|
|
49
49
|
}
|
|
50
|
+
beginRenovation(diff) {
|
|
51
|
+
if (this.renovation !== undefined)
|
|
52
|
+
throw misuse("renovation is in progress already");
|
|
53
|
+
const former = this.items$;
|
|
54
|
+
const renovation = new LinkedListRenovation(this, former, diff);
|
|
55
|
+
this.items$ = new LinkedSubList();
|
|
56
|
+
this.renovation = renovation;
|
|
57
|
+
return renovation;
|
|
58
|
+
}
|
|
59
|
+
endRenovation(error) {
|
|
60
|
+
const renovation = this.renovation;
|
|
61
|
+
if (renovation === undefined)
|
|
62
|
+
throw misuse("renovation is ended already");
|
|
63
|
+
const items = this.items$;
|
|
64
|
+
if (error === undefined) {
|
|
65
|
+
for (const x of renovation.lostItems()) {
|
|
66
|
+
if (!x.isManagedExternally) {
|
|
67
|
+
LinkedList.removeKey$(this, this.keyOf(x));
|
|
68
|
+
LinkedItem.setStatus$(x, Mark.removed, 0);
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
LinkedItem.link$(items, x, undefined);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
for (const x of renovation.lostItems()) {
|
|
76
|
+
LinkedItem.link$(items, x, undefined);
|
|
77
|
+
LinkedItem.setStatus$(x, Mark.prolonged, items.count);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
this.renovation = undefined;
|
|
81
|
+
}
|
|
50
82
|
static move$(list, item, before) {
|
|
51
83
|
LinkedItem.link$(list.items$, item, before);
|
|
52
84
|
}
|
|
@@ -175,3 +207,106 @@ export class LinkedSubList {
|
|
|
175
207
|
from.clear();
|
|
176
208
|
}
|
|
177
209
|
}
|
|
210
|
+
export class LinkedListRenovation {
|
|
211
|
+
constructor(list, former, diff) {
|
|
212
|
+
this.list = list;
|
|
213
|
+
this.diff = diff;
|
|
214
|
+
this.former = former;
|
|
215
|
+
this.expected = former.first;
|
|
216
|
+
this.absent = undefined;
|
|
217
|
+
}
|
|
218
|
+
lookup(key) {
|
|
219
|
+
let result = undefined;
|
|
220
|
+
if (key !== undefined && key !== this.absent) {
|
|
221
|
+
result = this.list.lookup(key);
|
|
222
|
+
if (result !== undefined) {
|
|
223
|
+
if (this.list.keyOf(result) !== key) {
|
|
224
|
+
this.absent = key;
|
|
225
|
+
result = undefined;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
this.absent = key;
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
tryToProlong(key, resolution, error) {
|
|
234
|
+
var _a, _b;
|
|
235
|
+
const list = this.list;
|
|
236
|
+
if (!list.isRenovationInProgress)
|
|
237
|
+
throw misuse(error !== null && error !== void 0 ? error : "renovation is no longer in progress");
|
|
238
|
+
let x = this.expected;
|
|
239
|
+
if (key !== (x ? list.keyOf(x) : undefined))
|
|
240
|
+
x = this.lookup(key);
|
|
241
|
+
if (x !== undefined) {
|
|
242
|
+
const result = this.list.items$;
|
|
243
|
+
if (x.list !== result) {
|
|
244
|
+
const next = x.next;
|
|
245
|
+
const expected = (_a = grabExternalIfAny(result, x)) !== null && _a !== void 0 ? _a : x;
|
|
246
|
+
LinkedItem.link$(result, x, undefined);
|
|
247
|
+
if (list.isStrictOrder && expected !== this.expected) {
|
|
248
|
+
LinkedItem.setStatus$(x, Mark.modified, result.count);
|
|
249
|
+
(_b = this.diff) === null || _b === void 0 ? void 0 : _b.push(x);
|
|
250
|
+
}
|
|
251
|
+
else
|
|
252
|
+
LinkedItem.setStatus$(x, Mark.prolonged, result.count);
|
|
253
|
+
this.expected = next;
|
|
254
|
+
if (resolution)
|
|
255
|
+
resolution.isDuplicate = false;
|
|
256
|
+
}
|
|
257
|
+
else if (resolution)
|
|
258
|
+
resolution.isDuplicate = true;
|
|
259
|
+
else
|
|
260
|
+
throw misuse(`duplicate linked item key: ${key}`);
|
|
261
|
+
}
|
|
262
|
+
else if (resolution)
|
|
263
|
+
resolution.isDuplicate = false;
|
|
264
|
+
return x;
|
|
265
|
+
}
|
|
266
|
+
thisIsAdded(item, before) {
|
|
267
|
+
var _a;
|
|
268
|
+
this.list.add(item, before);
|
|
269
|
+
LinkedItem.setStatus$(item, Mark.added, this.list.items$.count);
|
|
270
|
+
this.absent = undefined;
|
|
271
|
+
this.expected = undefined;
|
|
272
|
+
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
273
|
+
return item;
|
|
274
|
+
}
|
|
275
|
+
thisIsModified(item) {
|
|
276
|
+
if (item.list !== this.list.items$)
|
|
277
|
+
throw misuse("only prolonged items can be marked as modified");
|
|
278
|
+
const m = item.mark;
|
|
279
|
+
if (m === Mark.prolonged)
|
|
280
|
+
LinkedItem.setStatus$(item, Mark.modified, item.rank);
|
|
281
|
+
else if (m !== Mark.modified)
|
|
282
|
+
throw misuse("item is renovated already and cannot be marked as modified");
|
|
283
|
+
}
|
|
284
|
+
thisIsMoved(item, before) {
|
|
285
|
+
var _a;
|
|
286
|
+
if (item.list !== this.former)
|
|
287
|
+
throw misuse("cannot move item which doesn't belong to former list");
|
|
288
|
+
LinkedList.move$(this.list, item, before);
|
|
289
|
+
LinkedItem.setStatus$(item, Mark.modified, 0);
|
|
290
|
+
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
291
|
+
}
|
|
292
|
+
thisIsRemoved(item) {
|
|
293
|
+
var _a;
|
|
294
|
+
if (item.list !== this.former)
|
|
295
|
+
throw misuse("cannot remove item which doesn't belong to former list");
|
|
296
|
+
LinkedList.remove$(this.list, item);
|
|
297
|
+
LinkedItem.setStatus$(item, Mark.removed, 0);
|
|
298
|
+
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
299
|
+
}
|
|
300
|
+
get lostItemCount() { return this.former.count; }
|
|
301
|
+
lostItems() { return this.former.items(); }
|
|
302
|
+
}
|
|
303
|
+
function grabExternalIfAny(list, item) {
|
|
304
|
+
let x = item.prev;
|
|
305
|
+
let before = undefined;
|
|
306
|
+
while (x !== undefined && x.isManagedExternally) {
|
|
307
|
+
LinkedItem.link$(list, x, before);
|
|
308
|
+
before = x;
|
|
309
|
+
x = x.prev;
|
|
310
|
+
}
|
|
311
|
+
return before;
|
|
312
|
+
}
|
package/package.json
CHANGED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { LinkedList, LinkedItem } from "./LinkedList.js";
|
|
2
|
-
export declare class LinkedListRenovation<T extends LinkedItem<T>> {
|
|
3
|
-
readonly list: LinkedList<T>;
|
|
4
|
-
readonly diff: Array<T> | undefined;
|
|
5
|
-
private lost$;
|
|
6
|
-
private expected;
|
|
7
|
-
private absent;
|
|
8
|
-
constructor(list: LinkedList<T>, diff?: Array<T>);
|
|
9
|
-
lookup(key: string | undefined): T | undefined;
|
|
10
|
-
tryToProlonge(key: string, resolution?: {
|
|
11
|
-
isDuplicate: boolean;
|
|
12
|
-
}, error?: string): T | undefined;
|
|
13
|
-
thisIsAdded(item: T, before?: T): T;
|
|
14
|
-
thisIsModified(item: T): void;
|
|
15
|
-
thisIsMoved(item: T, before: T | undefined): void;
|
|
16
|
-
thisIsRemoved(item: T): void;
|
|
17
|
-
get lostItemCount(): number;
|
|
18
|
-
lostItems(): Generator<T>;
|
|
19
|
-
done(error?: unknown): void;
|
|
20
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { misuse } from "./Dbg.js";
|
|
2
|
-
import { LinkedList, LinkedItem, LinkedSubList, Mark } from "./LinkedList.js";
|
|
3
|
-
export class LinkedListRenovation {
|
|
4
|
-
constructor(list, diff) {
|
|
5
|
-
if (list.former$ !== undefined)
|
|
6
|
-
throw misuse("renovation is in progress already");
|
|
7
|
-
const former = list.items$;
|
|
8
|
-
this.list = list;
|
|
9
|
-
this.diff = diff;
|
|
10
|
-
this.lost$ = former;
|
|
11
|
-
this.expected = former.first;
|
|
12
|
-
this.absent = undefined;
|
|
13
|
-
list.former$ = former;
|
|
14
|
-
list.items$ = new LinkedSubList();
|
|
15
|
-
}
|
|
16
|
-
lookup(key) {
|
|
17
|
-
let result = undefined;
|
|
18
|
-
if (key !== undefined && key !== this.absent) {
|
|
19
|
-
result = this.list.lookup(key);
|
|
20
|
-
if (result !== undefined) {
|
|
21
|
-
if (this.list.keyOf(result) !== key) {
|
|
22
|
-
this.absent = key;
|
|
23
|
-
result = undefined;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else
|
|
27
|
-
this.absent = key;
|
|
28
|
-
}
|
|
29
|
-
return result;
|
|
30
|
-
}
|
|
31
|
-
tryToProlonge(key, resolution, error) {
|
|
32
|
-
var _a, _b;
|
|
33
|
-
const list = this.list;
|
|
34
|
-
if (!list.isRenovationInProgress)
|
|
35
|
-
throw misuse(error !== null && error !== void 0 ? error : "renovation is no longer in progress");
|
|
36
|
-
let x = this.expected;
|
|
37
|
-
if (key !== (x ? list.keyOf(x) : undefined))
|
|
38
|
-
x = this.lookup(key);
|
|
39
|
-
if (x !== undefined) {
|
|
40
|
-
const result = this.list.items$;
|
|
41
|
-
if (x.list !== result) {
|
|
42
|
-
const next = x.next;
|
|
43
|
-
const expected = (_a = grabExternalIfAny(result, x)) !== null && _a !== void 0 ? _a : x;
|
|
44
|
-
LinkedItem.link$(result, x, undefined);
|
|
45
|
-
if (list.isStrictOrder && expected !== this.expected) {
|
|
46
|
-
LinkedItem.setStatus$(x, Mark.modified, result.count);
|
|
47
|
-
(_b = this.diff) === null || _b === void 0 ? void 0 : _b.push(x);
|
|
48
|
-
}
|
|
49
|
-
else
|
|
50
|
-
LinkedItem.setStatus$(x, Mark.prolonged, result.count);
|
|
51
|
-
this.expected = next;
|
|
52
|
-
if (resolution)
|
|
53
|
-
resolution.isDuplicate = false;
|
|
54
|
-
}
|
|
55
|
-
else if (resolution)
|
|
56
|
-
resolution.isDuplicate = true;
|
|
57
|
-
else
|
|
58
|
-
throw misuse(`duplicate linked item key: ${key}`);
|
|
59
|
-
}
|
|
60
|
-
else if (resolution)
|
|
61
|
-
resolution.isDuplicate = false;
|
|
62
|
-
return x;
|
|
63
|
-
}
|
|
64
|
-
thisIsAdded(item, before) {
|
|
65
|
-
var _a;
|
|
66
|
-
this.list.add(item, before);
|
|
67
|
-
LinkedItem.setStatus$(item, Mark.added, this.list.items$.count);
|
|
68
|
-
this.absent = undefined;
|
|
69
|
-
this.expected = undefined;
|
|
70
|
-
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
71
|
-
return item;
|
|
72
|
-
}
|
|
73
|
-
thisIsModified(item) {
|
|
74
|
-
if (item.list !== this.list.items$)
|
|
75
|
-
throw misuse("only prolonged items can be marked as modified");
|
|
76
|
-
const m = item.mark;
|
|
77
|
-
if (m === Mark.prolonged)
|
|
78
|
-
LinkedItem.setStatus$(item, Mark.modified, item.rank);
|
|
79
|
-
else if (m !== Mark.modified)
|
|
80
|
-
throw misuse("item is renovated already and cannot be marked as modified");
|
|
81
|
-
}
|
|
82
|
-
thisIsMoved(item, before) {
|
|
83
|
-
var _a;
|
|
84
|
-
if (item.list !== this.list.former$)
|
|
85
|
-
throw misuse("cannot move item which doesn't belong to former list");
|
|
86
|
-
LinkedList.move$(this.list, item, before);
|
|
87
|
-
LinkedItem.setStatus$(item, Mark.modified, 0);
|
|
88
|
-
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
89
|
-
}
|
|
90
|
-
thisIsRemoved(item) {
|
|
91
|
-
var _a;
|
|
92
|
-
if (item.list !== this.list.former$)
|
|
93
|
-
throw misuse("cannot remove item which doesn't belong to former list");
|
|
94
|
-
LinkedList.remove$(this.list, item);
|
|
95
|
-
LinkedItem.setStatus$(item, Mark.removed, 0);
|
|
96
|
-
(_a = this.diff) === null || _a === void 0 ? void 0 : _a.push(item);
|
|
97
|
-
}
|
|
98
|
-
get lostItemCount() { return this.lost$.count; }
|
|
99
|
-
lostItems() { return this.lost$.items(); }
|
|
100
|
-
done(error) {
|
|
101
|
-
const list = this.list;
|
|
102
|
-
if (!list.isRenovationInProgress)
|
|
103
|
-
throw misuse("renovation is ended already");
|
|
104
|
-
const items = this.list.items$;
|
|
105
|
-
const lost = this.lost$;
|
|
106
|
-
if (error === undefined) {
|
|
107
|
-
for (const x of lost.items()) {
|
|
108
|
-
if (!x.isManagedExternally) {
|
|
109
|
-
LinkedList.removeKey$(list, list.keyOf(x));
|
|
110
|
-
LinkedItem.setStatus$(x, Mark.removed, 0);
|
|
111
|
-
}
|
|
112
|
-
else
|
|
113
|
-
LinkedItem.link$(items, x, undefined);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
for (const x of lost.items()) {
|
|
118
|
-
LinkedItem.link$(items, x, undefined);
|
|
119
|
-
LinkedItem.setStatus$(x, Mark.prolonged, items.count);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
list.former$ = undefined;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function grabExternalIfAny(list, item) {
|
|
126
|
-
let x = item.prev;
|
|
127
|
-
let before = undefined;
|
|
128
|
-
while (x !== undefined && x.isManagedExternally) {
|
|
129
|
-
LinkedItem.link$(list, x, before);
|
|
130
|
-
before = x;
|
|
131
|
-
x = x.prev;
|
|
132
|
-
}
|
|
133
|
-
return before;
|
|
134
|
-
}
|