reactronic 0.94.25036 → 0.95.25040
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 +67 -66
- package/build/dist/source/Enums.d.ts +3 -3
- package/build/dist/source/Enums.js +3 -3
- package/build/dist/source/OperationEx.d.ts +2 -2
- package/build/dist/source/OperationEx.js +5 -5
- package/build/dist/source/Options.d.ts +2 -2
- package/build/dist/source/Pipe.d.ts +2 -2
- package/build/dist/source/Pipe.js +2 -2
- package/build/dist/source/Ref.d.ts +2 -2
- package/build/dist/source/Ref.js +5 -5
- package/build/dist/source/System.d.ts +14 -14
- package/build/dist/source/System.js +22 -22
- package/build/dist/source/api.d.ts +9 -9
- package/build/dist/source/api.js +7 -7
- package/build/dist/source/core/Changeset.js +1 -1
- package/build/dist/source/core/Data.d.ts +1 -1
- package/build/dist/source/core/Indicator.d.ts +2 -2
- package/build/dist/source/core/Indicator.js +2 -2
- package/build/dist/source/core/Journal.d.ts +2 -2
- package/build/dist/source/core/Journal.js +2 -2
- package/build/dist/source/core/Mvcc.d.ts +10 -10
- package/build/dist/source/core/Mvcc.js +19 -19
- package/build/dist/source/core/MvccArray.d.ts +3 -3
- package/build/dist/source/core/MvccArray.js +4 -4
- package/build/dist/source/core/MvccMap.d.ts +3 -3
- package/build/dist/source/core/MvccMap.js +4 -4
- package/build/dist/source/core/MvccReconciliationList.d.ts +28 -0
- package/build/dist/source/core/MvccReconciliationList.js +26 -0
- package/build/dist/source/core/Operation.d.ts +8 -8
- package/build/dist/source/core/Operation.js +41 -41
- package/build/dist/source/core/Transaction.js +28 -28
- package/build/dist/source/core/TreeNode.d.ts +19 -19
- package/build/dist/source/core/TreeNode.js +58 -58
- package/build/dist/source/util/LinkedList.d.ts +52 -0
- package/build/dist/source/util/LinkedList.js +177 -0
- package/build/dist/source/util/LinkedListRenovation.d.ts +20 -0
- package/build/dist/source/util/LinkedListRenovation.js +134 -0
- package/build/dist/source/util/{ScriptedList.d.ts → ReconciliationList.d.ts} +17 -15
- package/build/dist/source/util/{ScriptedList.js → ReconciliationList.js} +91 -90
- package/package.json +10 -9
- package/build/dist/source/core/MvccMergeList.d.ts +0 -27
- package/build/dist/source/core/MvccMergeList.js +0 -25
|
@@ -0,0 +1,134 @@
|
|
|
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
|
+
}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
export type GetListItemKey<T = unknown> = (item: T) => string | undefined;
|
|
2
|
-
export type
|
|
2
|
+
export type ReconciliationListReader<T> = {
|
|
3
3
|
readonly isStrict: boolean;
|
|
4
4
|
readonly count: number;
|
|
5
5
|
readonly countOfAdded: number;
|
|
6
6
|
readonly countOfRemoved: number;
|
|
7
|
-
readonly
|
|
7
|
+
readonly isReconciliationInProgress: boolean;
|
|
8
8
|
lookup(key: string): LinkedItem<T> | undefined;
|
|
9
9
|
firstItem(): LinkedItem<T> | undefined;
|
|
10
10
|
lastItem(): LinkedItem<T> | undefined;
|
|
11
11
|
items(onlyAfter?: LinkedItem<T>): Generator<LinkedItem<T>>;
|
|
12
|
-
itemsAdded(
|
|
13
|
-
itemsRemoved(
|
|
12
|
+
itemsAdded(clear?: boolean): Generator<LinkedItem<T>>;
|
|
13
|
+
itemsRemoved(clear?: boolean): Generator<LinkedItem<T>>;
|
|
14
14
|
isAdded(item: LinkedItem<T>): boolean;
|
|
15
15
|
isMoved(item: LinkedItem<T>): boolean;
|
|
16
16
|
isRemoved(item: LinkedItem<T>): boolean;
|
|
17
|
-
|
|
17
|
+
isActual(item: LinkedItem<T>): boolean;
|
|
18
|
+
isExternal(item: LinkedItem<T>): boolean;
|
|
18
19
|
};
|
|
19
20
|
export type LinkedItem<T> = {
|
|
20
21
|
readonly instance: T;
|
|
@@ -23,12 +24,12 @@ export type LinkedItem<T> = {
|
|
|
23
24
|
readonly prev?: LinkedItem<T>;
|
|
24
25
|
aux?: LinkedItem<T>;
|
|
25
26
|
};
|
|
26
|
-
export declare class
|
|
27
|
+
export declare class ReconciliationList<T> implements ReconciliationListReader<T> {
|
|
27
28
|
readonly getKey: GetListItemKey<T>;
|
|
28
29
|
private strict;
|
|
29
30
|
private map;
|
|
30
|
-
private
|
|
31
|
-
private
|
|
31
|
+
private tag;
|
|
32
|
+
private actual;
|
|
32
33
|
private added;
|
|
33
34
|
private removed;
|
|
34
35
|
private lastNotFoundKey;
|
|
@@ -39,7 +40,7 @@ export declare class ScriptedList<T> implements ScriptedListReader<T> {
|
|
|
39
40
|
get count(): number;
|
|
40
41
|
get countOfAdded(): number;
|
|
41
42
|
get countOfRemoved(): number;
|
|
42
|
-
get
|
|
43
|
+
get isReconciliationInProgress(): boolean;
|
|
43
44
|
lookup(key: string | undefined): LinkedItem<T> | undefined;
|
|
44
45
|
tryReuse(key: string, resolution?: {
|
|
45
46
|
isDuplicate: boolean;
|
|
@@ -47,18 +48,19 @@ export declare class ScriptedList<T> implements ScriptedListReader<T> {
|
|
|
47
48
|
add(instance: T): LinkedItem<T>;
|
|
48
49
|
remove(item: LinkedItem<T>): void;
|
|
49
50
|
move(item: LinkedItem<T>, after: LinkedItem<T>): void;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
beginReconciliation(): void;
|
|
52
|
+
endReconciliation(error?: unknown): void;
|
|
53
|
+
clearAddedAndRemoved(): void;
|
|
53
54
|
firstItem(): LinkedItem<T> | undefined;
|
|
54
55
|
lastItem(): LinkedItem<T> | undefined;
|
|
55
56
|
items(onlyAfter?: LinkedItem<T>): Generator<LinkedItem<T>>;
|
|
56
|
-
itemsAdded(
|
|
57
|
-
itemsRemoved(
|
|
57
|
+
itemsAdded(clear?: boolean): Generator<LinkedItem<T>>;
|
|
58
|
+
itemsRemoved(clear?: boolean): Generator<LinkedItem<T>>;
|
|
58
59
|
isAdded(item: LinkedItem<T>): boolean;
|
|
59
60
|
isMoved(item: LinkedItem<T>): boolean;
|
|
60
61
|
isRemoved(item: LinkedItem<T>): boolean;
|
|
61
|
-
|
|
62
|
+
isActual(item: LinkedItem<T>): boolean;
|
|
63
|
+
isExternal(item: LinkedItem<T>): boolean;
|
|
62
64
|
markAsMoved(item: LinkedItem<T>): void;
|
|
63
65
|
static createItem<T>(instance: T): LinkedItem<T>;
|
|
64
66
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { misuse } from "./Dbg.js";
|
|
2
|
-
export class
|
|
2
|
+
export class ReconciliationList {
|
|
3
3
|
constructor(getKey, strict = false) {
|
|
4
4
|
this.getKey = getKey;
|
|
5
5
|
this.strict = strict;
|
|
6
6
|
this.map = new Map();
|
|
7
|
-
this.
|
|
8
|
-
this.
|
|
7
|
+
this.tag = ~0;
|
|
8
|
+
this.actual = new LinkedItemChain();
|
|
9
9
|
this.added = new LinkedItemChain();
|
|
10
10
|
this.removed = new LinkedItemChain();
|
|
11
11
|
this.lastNotFoundKey = undefined;
|
|
@@ -13,12 +13,12 @@ export class ScriptedList {
|
|
|
13
13
|
}
|
|
14
14
|
get isStrict() { return this.strict; }
|
|
15
15
|
set isStrict(value) {
|
|
16
|
-
if (this.
|
|
17
|
-
throw misuse("cannot change strict mode in the middle of
|
|
16
|
+
if (this.isReconciliationInProgress && this.actual.count > 0)
|
|
17
|
+
throw misuse("cannot change strict mode in the middle of reconciliation");
|
|
18
18
|
this.strict = value;
|
|
19
19
|
}
|
|
20
20
|
get count() {
|
|
21
|
-
return this.
|
|
21
|
+
return this.actual.count;
|
|
22
22
|
}
|
|
23
23
|
get countOfAdded() {
|
|
24
24
|
return this.added.count;
|
|
@@ -26,8 +26,8 @@ export class ScriptedList {
|
|
|
26
26
|
get countOfRemoved() {
|
|
27
27
|
return this.removed.count;
|
|
28
28
|
}
|
|
29
|
-
get
|
|
30
|
-
return this.
|
|
29
|
+
get isReconciliationInProgress() {
|
|
30
|
+
return this.tag > 0;
|
|
31
31
|
}
|
|
32
32
|
lookup(key) {
|
|
33
33
|
let result = undefined;
|
|
@@ -45,21 +45,21 @@ export class ScriptedList {
|
|
|
45
45
|
return result;
|
|
46
46
|
}
|
|
47
47
|
tryReuse(key, resolution, error) {
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
throw misuse(error !== null && error !== void 0 ? error : "
|
|
48
|
+
const tag = this.tag;
|
|
49
|
+
if (tag < 0)
|
|
50
|
+
throw misuse(error !== null && error !== void 0 ? error : "reconciliation is not in progress");
|
|
51
51
|
let item = this.strictNextItem;
|
|
52
52
|
if (key !== (item ? this.getKey(item.instance) : undefined))
|
|
53
53
|
item = this.lookup(key);
|
|
54
54
|
if (item) {
|
|
55
|
-
if (item.
|
|
56
|
-
item.
|
|
55
|
+
if (item.tag !== tag) {
|
|
56
|
+
item.tag = tag;
|
|
57
57
|
if (this.strict && item !== this.strictNextItem)
|
|
58
|
-
item.
|
|
58
|
+
item.moving = tag;
|
|
59
59
|
this.strictNextItem = item.next;
|
|
60
60
|
this.removed.exclude(item);
|
|
61
|
-
item.index = this.
|
|
62
|
-
this.
|
|
61
|
+
item.index = this.actual.count;
|
|
62
|
+
this.actual.include(item);
|
|
63
63
|
if (resolution)
|
|
64
64
|
resolution.isDuplicate = false;
|
|
65
65
|
}
|
|
@@ -76,55 +76,52 @@ export class ScriptedList {
|
|
|
76
76
|
const key = this.getKey(instance);
|
|
77
77
|
if (this.lookup(key) !== undefined)
|
|
78
78
|
throw misuse(`key is already in use: ${key}`);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
cycle = ~this.cycle + 1;
|
|
82
|
-
this.cycle = ~cycle;
|
|
83
|
-
}
|
|
84
|
-
const item = new LinkedItemImpl(instance, cycle);
|
|
79
|
+
const tag = this.tag > 0 ? this.tag : 0;
|
|
80
|
+
const item = new LinkedItem$(instance, tag);
|
|
85
81
|
this.map.set(key, item);
|
|
86
82
|
this.lastNotFoundKey = undefined;
|
|
87
83
|
this.strictNextItem = undefined;
|
|
88
|
-
item.index = this.
|
|
89
|
-
this.
|
|
90
|
-
|
|
84
|
+
item.index = this.actual.count;
|
|
85
|
+
this.actual.include(item);
|
|
86
|
+
if (tag !== 0)
|
|
87
|
+
this.added.includeAux(item);
|
|
91
88
|
return item;
|
|
92
89
|
}
|
|
93
90
|
remove(item) {
|
|
94
91
|
const t = item;
|
|
95
92
|
if (!this.isRemoved(t)) {
|
|
96
|
-
this.
|
|
93
|
+
this.actual.exclude(t);
|
|
97
94
|
this.removed.include(t);
|
|
98
|
-
t.
|
|
95
|
+
t.tag--;
|
|
99
96
|
}
|
|
100
97
|
}
|
|
101
98
|
move(item, after) {
|
|
102
99
|
throw misuse("not implemented");
|
|
103
100
|
}
|
|
104
|
-
|
|
105
|
-
if (this.
|
|
106
|
-
throw misuse("
|
|
107
|
-
this.
|
|
108
|
-
this.strictNextItem = this.
|
|
109
|
-
this.removed.grab(this.
|
|
110
|
-
this.added.
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!this.
|
|
114
|
-
throw misuse("
|
|
115
|
-
this.
|
|
101
|
+
beginReconciliation() {
|
|
102
|
+
if (this.isReconciliationInProgress)
|
|
103
|
+
throw misuse("reconciliation is in progress already");
|
|
104
|
+
this.tag = ~this.tag + 1;
|
|
105
|
+
this.strictNextItem = this.actual.first;
|
|
106
|
+
this.removed.grab(this.actual, false);
|
|
107
|
+
this.added.clear();
|
|
108
|
+
}
|
|
109
|
+
endReconciliation(error) {
|
|
110
|
+
if (!this.isReconciliationInProgress)
|
|
111
|
+
throw misuse("reconciliation is ended already");
|
|
112
|
+
this.tag = ~this.tag;
|
|
116
113
|
if (error === undefined) {
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
114
|
+
const actualCount = this.actual.count;
|
|
115
|
+
if (actualCount > 0) {
|
|
119
116
|
const getKey = this.getKey;
|
|
120
|
-
if (
|
|
117
|
+
if (actualCount > this.removed.count) {
|
|
121
118
|
const map = this.map;
|
|
122
119
|
for (const x of this.removed.items())
|
|
123
120
|
map.delete(getKey(x.instance));
|
|
124
121
|
}
|
|
125
122
|
else {
|
|
126
123
|
const map = this.map = new Map();
|
|
127
|
-
for (const x of this.
|
|
124
|
+
for (const x of this.actual.items())
|
|
128
125
|
map.set(getKey(x.instance), x);
|
|
129
126
|
}
|
|
130
127
|
}
|
|
@@ -132,35 +129,35 @@ export class ScriptedList {
|
|
|
132
129
|
this.map = new Map();
|
|
133
130
|
}
|
|
134
131
|
else {
|
|
135
|
-
this.
|
|
132
|
+
this.actual.grab(this.removed, true);
|
|
136
133
|
const getKey = this.getKey;
|
|
137
|
-
for (const x of this.added.
|
|
134
|
+
for (const x of this.added.itemsAux()) {
|
|
138
135
|
this.map.delete(getKey(x.instance));
|
|
139
|
-
this.
|
|
136
|
+
this.actual.exclude(x);
|
|
140
137
|
}
|
|
141
|
-
this.added.
|
|
138
|
+
this.added.clear();
|
|
142
139
|
}
|
|
143
140
|
}
|
|
144
|
-
|
|
145
|
-
this.removed.
|
|
146
|
-
this.added.
|
|
141
|
+
clearAddedAndRemoved() {
|
|
142
|
+
this.removed.clear();
|
|
143
|
+
this.added.clear();
|
|
147
144
|
}
|
|
148
145
|
firstItem() {
|
|
149
|
-
return this.
|
|
146
|
+
return this.actual.first;
|
|
150
147
|
}
|
|
151
148
|
lastItem() {
|
|
152
|
-
return this.
|
|
149
|
+
return this.actual.last;
|
|
153
150
|
}
|
|
154
151
|
*items(onlyAfter) {
|
|
155
152
|
var _a;
|
|
156
|
-
let x = (_a = onlyAfter === null || onlyAfter === void 0 ? void 0 : onlyAfter.next) !== null && _a !== void 0 ? _a : this.
|
|
153
|
+
let x = (_a = onlyAfter === null || onlyAfter === void 0 ? void 0 : onlyAfter.next) !== null && _a !== void 0 ? _a : this.actual.first;
|
|
157
154
|
while (x !== undefined) {
|
|
158
155
|
const next = x.next;
|
|
159
156
|
yield x;
|
|
160
157
|
x = next;
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
|
-
*itemsAdded(
|
|
160
|
+
*itemsAdded(clear) {
|
|
164
161
|
let x = this.added.first;
|
|
165
162
|
while (x !== undefined) {
|
|
166
163
|
const next = x.aux;
|
|
@@ -168,57 +165,61 @@ export class ScriptedList {
|
|
|
168
165
|
yield x;
|
|
169
166
|
x = next;
|
|
170
167
|
}
|
|
171
|
-
if (
|
|
172
|
-
this.added.
|
|
168
|
+
if (clear)
|
|
169
|
+
this.added.clear();
|
|
173
170
|
}
|
|
174
|
-
*itemsRemoved(
|
|
171
|
+
*itemsRemoved(clear) {
|
|
175
172
|
let x = this.removed.first;
|
|
176
173
|
while (x !== undefined) {
|
|
177
174
|
const next = x.next;
|
|
178
175
|
yield x;
|
|
179
176
|
x = next;
|
|
180
177
|
}
|
|
181
|
-
if (
|
|
182
|
-
this.removed.
|
|
178
|
+
if (clear)
|
|
179
|
+
this.removed.clear();
|
|
183
180
|
}
|
|
184
181
|
isAdded(item) {
|
|
185
182
|
const t = item;
|
|
186
|
-
let
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
return t.
|
|
183
|
+
let tag = this.tag;
|
|
184
|
+
if (tag < 0)
|
|
185
|
+
tag = ~tag;
|
|
186
|
+
return t.moving === ~tag && t.tag > 0;
|
|
190
187
|
}
|
|
191
188
|
isMoved(item) {
|
|
192
189
|
const t = item;
|
|
193
|
-
let
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
return t.
|
|
190
|
+
let tag = this.tag;
|
|
191
|
+
if (tag < 0)
|
|
192
|
+
tag = ~tag;
|
|
193
|
+
return t.moving === tag && t.tag > 0;
|
|
197
194
|
}
|
|
198
195
|
isRemoved(item) {
|
|
199
196
|
const t = item;
|
|
200
|
-
const
|
|
201
|
-
return
|
|
197
|
+
const tag = this.tag;
|
|
198
|
+
return tag > 0 ? t.tag < tag : t.tag < tag - 1;
|
|
199
|
+
}
|
|
200
|
+
isActual(item) {
|
|
201
|
+
const t = item;
|
|
202
|
+
return t.tag === this.tag;
|
|
202
203
|
}
|
|
203
|
-
|
|
204
|
+
isExternal(item) {
|
|
204
205
|
const t = item;
|
|
205
|
-
return t.
|
|
206
|
+
return t.tag === 0;
|
|
206
207
|
}
|
|
207
208
|
markAsMoved(item) {
|
|
208
209
|
const t = item;
|
|
209
|
-
if (t.
|
|
210
|
-
t.
|
|
210
|
+
if (t.tag > 0)
|
|
211
|
+
t.moving = t.tag;
|
|
211
212
|
}
|
|
212
213
|
static createItem(instance) {
|
|
213
|
-
return new
|
|
214
|
+
return new LinkedItem$(instance, 0);
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
|
-
class
|
|
217
|
-
constructor(instance,
|
|
217
|
+
class LinkedItem$ {
|
|
218
|
+
constructor(instance, tag) {
|
|
218
219
|
this.instance = instance;
|
|
219
220
|
this.index = -1;
|
|
220
|
-
this.
|
|
221
|
-
this.
|
|
221
|
+
this.tag = tag;
|
|
222
|
+
this.moving = ~tag;
|
|
222
223
|
this.next = undefined;
|
|
223
224
|
this.prev = undefined;
|
|
224
225
|
this.aux = undefined;
|
|
@@ -238,7 +239,7 @@ class LinkedItemChain {
|
|
|
238
239
|
x = next;
|
|
239
240
|
}
|
|
240
241
|
}
|
|
241
|
-
*
|
|
242
|
+
*itemsAux() {
|
|
242
243
|
let x = this.first;
|
|
243
244
|
while (x !== undefined) {
|
|
244
245
|
const next = x.aux;
|
|
@@ -246,7 +247,7 @@ class LinkedItemChain {
|
|
|
246
247
|
x = next;
|
|
247
248
|
}
|
|
248
249
|
}
|
|
249
|
-
|
|
250
|
+
clear() {
|
|
250
251
|
this.count = 0;
|
|
251
252
|
this.first = undefined;
|
|
252
253
|
this.last = undefined;
|
|
@@ -267,7 +268,7 @@ class LinkedItemChain {
|
|
|
267
268
|
this.first = head;
|
|
268
269
|
this.last = from.last;
|
|
269
270
|
}
|
|
270
|
-
from.
|
|
271
|
+
from.clear();
|
|
271
272
|
}
|
|
272
273
|
include(item) {
|
|
273
274
|
const last = this.last;
|
|
@@ -279,6 +280,15 @@ class LinkedItemChain {
|
|
|
279
280
|
this.first = this.last = item;
|
|
280
281
|
this.count++;
|
|
281
282
|
}
|
|
283
|
+
includeAux(item) {
|
|
284
|
+
item.aux = undefined;
|
|
285
|
+
const last = this.last;
|
|
286
|
+
if (last)
|
|
287
|
+
this.last = last.aux = item;
|
|
288
|
+
else
|
|
289
|
+
this.first = this.last = item;
|
|
290
|
+
this.count++;
|
|
291
|
+
}
|
|
282
292
|
exclude(item) {
|
|
283
293
|
if (item.prev !== undefined)
|
|
284
294
|
item.prev.next = item.next;
|
|
@@ -288,13 +298,4 @@ class LinkedItemChain {
|
|
|
288
298
|
this.first = item.next;
|
|
289
299
|
this.count--;
|
|
290
300
|
}
|
|
291
|
-
aux(item) {
|
|
292
|
-
item.aux = undefined;
|
|
293
|
-
const last = this.last;
|
|
294
|
-
if (last)
|
|
295
|
-
this.last = last.aux = item;
|
|
296
|
-
else
|
|
297
|
-
this.first = this.last = item;
|
|
298
|
-
this.count++;
|
|
299
|
-
}
|
|
300
301
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactronic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.95.25040",
|
|
4
4
|
"description": "Reactronic - Transactional Reactive State Management",
|
|
5
5
|
"publisher": "Nezaboodka Software",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,16 +31,17 @@
|
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://github.com/nezaboodka/reactronic/blob/master/README.md#readme",
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@types/node": "
|
|
35
|
-
"@types/react": "19.
|
|
36
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
37
|
-
"@typescript-eslint/parser": "8.
|
|
38
|
-
"
|
|
34
|
+
"@types/node": "24.10.2",
|
|
35
|
+
"@types/react": "19.2.7",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "8.49.0",
|
|
37
|
+
"@typescript-eslint/parser": "8.49.0",
|
|
38
|
+
"tsimp": "2.0.12",
|
|
39
|
+
"ava": "6.4.1",
|
|
39
40
|
"c8": "10.1.3",
|
|
40
|
-
"eslint": "9.
|
|
41
|
-
"react": "19.
|
|
41
|
+
"eslint": "9.39.1",
|
|
42
|
+
"react": "19.2.1",
|
|
42
43
|
"ts-node": "10.9.2",
|
|
43
|
-
"typescript": "5.
|
|
44
|
+
"typescript": "5.9.3"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
47
|
"build": "eslint source/**.ts test/**.test.ts react/**.tsx && tsc",
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ScriptedList, LinkedItem, ScriptedListReader } from "../util/ScriptedList.js";
|
|
2
|
-
import { ObservableObject } from "./Mvcc.js";
|
|
3
|
-
export declare abstract class ObservableScriptedList<T> extends ObservableObject implements ScriptedListReader<T> {
|
|
4
|
-
protected abstract impl: ScriptedList<T>;
|
|
5
|
-
get isStrict(): boolean;
|
|
6
|
-
get count(): number;
|
|
7
|
-
get countOfAdded(): number;
|
|
8
|
-
get countOfRemoved(): number;
|
|
9
|
-
get isScriptingInProgress(): boolean;
|
|
10
|
-
lookup(key: string): LinkedItem<T> | undefined;
|
|
11
|
-
tryMergeAsExisting(key: string): LinkedItem<T> | undefined;
|
|
12
|
-
mergeAsAdded(instance: T): LinkedItem<T>;
|
|
13
|
-
mergeAsRemoved(item: LinkedItem<T>): void;
|
|
14
|
-
move(item: LinkedItem<T>, after: LinkedItem<T>): void;
|
|
15
|
-
beginMerge(): void;
|
|
16
|
-
endMerge(error?: unknown): void;
|
|
17
|
-
resetAddedAndRemovedLists(): void;
|
|
18
|
-
firstItem(): LinkedItem<T> | undefined;
|
|
19
|
-
lastItem(): LinkedItem<T> | undefined;
|
|
20
|
-
items(): Generator<LinkedItem<T>>;
|
|
21
|
-
itemsAdded(reset?: boolean): Generator<LinkedItem<T>>;
|
|
22
|
-
itemsRemoved(reset?: boolean): Generator<LinkedItem<T>>;
|
|
23
|
-
isAdded(item: LinkedItem<T>): boolean;
|
|
24
|
-
isMoved(item: LinkedItem<T>): boolean;
|
|
25
|
-
isRemoved(item: LinkedItem<T>): boolean;
|
|
26
|
-
isAlive(item: LinkedItem<T>): boolean;
|
|
27
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { ObservableObject } from "./Mvcc.js";
|
|
2
|
-
export class ObservableScriptedList extends ObservableObject {
|
|
3
|
-
get isStrict() { return this.impl.isStrict; }
|
|
4
|
-
get count() { return this.impl.count; }
|
|
5
|
-
get countOfAdded() { return this.impl.countOfAdded; }
|
|
6
|
-
get countOfRemoved() { return this.impl.countOfRemoved; }
|
|
7
|
-
get isScriptingInProgress() { return this.impl.isScriptingInProgress; }
|
|
8
|
-
lookup(key) { return this.impl.lookup(key); }
|
|
9
|
-
tryMergeAsExisting(key) { return this.impl.tryReuse(key); }
|
|
10
|
-
mergeAsAdded(instance) { return this.impl.add(instance); }
|
|
11
|
-
mergeAsRemoved(item) { return this.impl.remove(item); }
|
|
12
|
-
move(item, after) { this.impl.move(item, after); }
|
|
13
|
-
beginMerge() { this.impl.beginScriptExecution(); }
|
|
14
|
-
endMerge(error) { this.impl.endScriptExecution(error); }
|
|
15
|
-
resetAddedAndRemovedLists() { this.impl.resetAddedAndRemovedLists(); }
|
|
16
|
-
firstItem() { return this.impl.firstItem(); }
|
|
17
|
-
lastItem() { return this.impl.lastItem(); }
|
|
18
|
-
items() { return this.impl.items(); }
|
|
19
|
-
itemsAdded(reset) { return this.impl.itemsAdded(reset); }
|
|
20
|
-
itemsRemoved(reset) { return this.impl.itemsRemoved(reset); }
|
|
21
|
-
isAdded(item) { return this.impl.isAdded(item); }
|
|
22
|
-
isMoved(item) { return this.impl.isMoved(item); }
|
|
23
|
-
isRemoved(item) { return this.impl.isRemoved(item); }
|
|
24
|
-
isAlive(item) { return this.impl.isAlive(item); }
|
|
25
|
-
}
|