reactronic 0.94.25036 → 0.94.25037
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/build/dist/source/api.d.ts +2 -2
- package/build/dist/source/api.js +1 -1
- package/build/dist/source/core/{MvccMergeList.d.ts → MvccReconciliationList.d.ts} +5 -5
- package/build/dist/source/core/{MvccMergeList.js → MvccReconciliationList.js} +5 -5
- package/build/dist/source/core/TreeNode.d.ts +3 -3
- package/build/dist/source/core/TreeNode.js +6 -6
- package/build/dist/source/util/{ScriptedList.d.ts → ReconciliationList.d.ts} +10 -10
- package/build/dist/source/util/{ScriptedList.js → ReconciliationList.js} +61 -61
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { all, pause, proceedSyncOrAsync } from "./util/Utils.js";
|
|
2
2
|
export { Uri } from "./util/Uri.js";
|
|
3
|
-
export {
|
|
4
|
-
export type { LinkedItem,
|
|
3
|
+
export { ReconciliationList } from "./util/ReconciliationList.js";
|
|
4
|
+
export type { LinkedItem, ReconciliationListReader } from "./util/ReconciliationList.js";
|
|
5
5
|
export { SealedArray } from "./util/SealedArray.js";
|
|
6
6
|
export { SealedMap } from "./util/SealedMap.js";
|
|
7
7
|
export { SealedSet } from "./util/SealedSet.js";
|
package/build/dist/source/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { all, pause, proceedSyncOrAsync } from "./util/Utils.js";
|
|
2
2
|
export { Uri } from "./util/Uri.js";
|
|
3
|
-
export {
|
|
3
|
+
export { ReconciliationList } from "./util/ReconciliationList.js";
|
|
4
4
|
export { SealedArray } from "./util/SealedArray.js";
|
|
5
5
|
export { SealedMap } from "./util/SealedMap.js";
|
|
6
6
|
export { SealedSet } from "./util/SealedSet.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReconciliationList, LinkedItem, ReconciliationListReader } from "../util/ReconciliationList.js";
|
|
2
2
|
import { ObservableObject } from "./Mvcc.js";
|
|
3
|
-
export declare abstract class
|
|
4
|
-
protected abstract impl:
|
|
3
|
+
export declare abstract class ObservableReconciliationList<T> extends ObservableObject implements ReconciliationListReader<T> {
|
|
4
|
+
protected abstract impl: ReconciliationList<T>;
|
|
5
5
|
get isStrict(): boolean;
|
|
6
6
|
get count(): number;
|
|
7
7
|
get countOfAdded(): number;
|
|
8
8
|
get countOfRemoved(): number;
|
|
9
|
-
get
|
|
9
|
+
get isReconciliationInProgress(): boolean;
|
|
10
10
|
lookup(key: string): LinkedItem<T> | undefined;
|
|
11
11
|
tryMergeAsExisting(key: string): LinkedItem<T> | undefined;
|
|
12
12
|
mergeAsAdded(instance: T): LinkedItem<T>;
|
|
@@ -23,5 +23,5 @@ export declare abstract class ObservableScriptedList<T> extends ObservableObject
|
|
|
23
23
|
isAdded(item: LinkedItem<T>): boolean;
|
|
24
24
|
isMoved(item: LinkedItem<T>): boolean;
|
|
25
25
|
isRemoved(item: LinkedItem<T>): boolean;
|
|
26
|
-
|
|
26
|
+
isFresh(item: LinkedItem<T>): boolean;
|
|
27
27
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ObservableObject } from "./Mvcc.js";
|
|
2
|
-
export class
|
|
2
|
+
export class ObservableReconciliationList extends ObservableObject {
|
|
3
3
|
get isStrict() { return this.impl.isStrict; }
|
|
4
4
|
get count() { return this.impl.count; }
|
|
5
5
|
get countOfAdded() { return this.impl.countOfAdded; }
|
|
6
6
|
get countOfRemoved() { return this.impl.countOfRemoved; }
|
|
7
|
-
get
|
|
7
|
+
get isReconciliationInProgress() { return this.impl.isReconciliationInProgress; }
|
|
8
8
|
lookup(key) { return this.impl.lookup(key); }
|
|
9
9
|
tryMergeAsExisting(key) { return this.impl.tryReuse(key); }
|
|
10
10
|
mergeAsAdded(instance) { return this.impl.add(instance); }
|
|
11
11
|
mergeAsRemoved(item) { return this.impl.remove(item); }
|
|
12
12
|
move(item, after) { this.impl.move(item, after); }
|
|
13
|
-
beginMerge() { this.impl.
|
|
14
|
-
endMerge(error) { this.impl.
|
|
13
|
+
beginMerge() { this.impl.beginReconciliation(); }
|
|
14
|
+
endMerge(error) { this.impl.endReconciliation(error); }
|
|
15
15
|
resetAddedAndRemovedLists() { this.impl.resetAddedAndRemovedLists(); }
|
|
16
16
|
firstItem() { return this.impl.firstItem(); }
|
|
17
17
|
lastItem() { return this.impl.lastItem(); }
|
|
@@ -21,5 +21,5 @@ export class ObservableScriptedList extends ObservableObject {
|
|
|
21
21
|
isAdded(item) { return this.impl.isAdded(item); }
|
|
22
22
|
isMoved(item) { return this.impl.isMoved(item); }
|
|
23
23
|
isRemoved(item) { return this.impl.isRemoved(item); }
|
|
24
|
-
|
|
24
|
+
isFresh(item) { return this.impl.isFresh(item); }
|
|
25
25
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LoggingOptions } from "../Logging.js";
|
|
2
|
-
import {
|
|
2
|
+
import { ReconciliationList, ReconciliationListReader, LinkedItem } from "../util/ReconciliationList.js";
|
|
3
3
|
import { Priority, Mode } from "../Enums.js";
|
|
4
4
|
import { ReactivityOptions } from "../Options.js";
|
|
5
5
|
import { ObservableObject } from "../core/Mvcc.js";
|
|
@@ -23,7 +23,7 @@ export declare abstract class ReactiveTreeNode<E = unknown> {
|
|
|
23
23
|
abstract readonly owner: ReactiveTreeNode;
|
|
24
24
|
abstract element: E;
|
|
25
25
|
abstract readonly host: ReactiveTreeNode;
|
|
26
|
-
abstract readonly children:
|
|
26
|
+
abstract readonly children: ReconciliationListReader<ReactiveTreeNode>;
|
|
27
27
|
abstract readonly slot: LinkedItem<ReactiveTreeNode<E>> | undefined;
|
|
28
28
|
abstract readonly stamp: number;
|
|
29
29
|
abstract readonly outer: ReactiveTreeNode;
|
|
@@ -112,7 +112,7 @@ declare class ReactiveTreeNodeImpl<E = unknown> extends ReactiveTreeNode<E> {
|
|
|
112
112
|
readonly owner: ReactiveTreeNodeImpl;
|
|
113
113
|
readonly element: E;
|
|
114
114
|
host: ReactiveTreeNodeImpl;
|
|
115
|
-
readonly children:
|
|
115
|
+
readonly children: ReconciliationList<ReactiveTreeNodeImpl>;
|
|
116
116
|
slot: LinkedItem<ReactiveTreeNodeImpl<E>> | undefined;
|
|
117
117
|
stamp: number;
|
|
118
118
|
outer: ReactiveTreeNodeImpl;
|
|
@@ -18,7 +18,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
18
18
|
};
|
|
19
19
|
import { misuse } from "../util/Dbg.js";
|
|
20
20
|
import { Uri } from "../util/Uri.js";
|
|
21
|
-
import {
|
|
21
|
+
import { ReconciliationList } from "../util/ReconciliationList.js";
|
|
22
22
|
import { emitLetters, flags, getCallerInfo, proceedSyncOrAsync } from "../util/Utils.js";
|
|
23
23
|
import { Priority, Mode, Isolation, Reentrance } from "../Enums.js";
|
|
24
24
|
import { ObservableObject } from "../core/Mvcc.js";
|
|
@@ -57,7 +57,7 @@ export function declare(driver, scriptOrDeclaration, scriptAsync, key, mode, pre
|
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
59
|
result = new ReactiveTreeNodeImpl(effectiveKey || generateKey(owner), driver, declaration, owner);
|
|
60
|
-
result.slot =
|
|
60
|
+
result.slot = ReconciliationList.createItem(result);
|
|
61
61
|
}
|
|
62
62
|
return result;
|
|
63
63
|
}
|
|
@@ -270,7 +270,7 @@ class ReactiveTreeNodeImpl extends ReactiveTreeNode {
|
|
|
270
270
|
}
|
|
271
271
|
this.element = driver.create(this);
|
|
272
272
|
this.host = thisAsUnknown;
|
|
273
|
-
this.children = new
|
|
273
|
+
this.children = new ReconciliationList(getNodeKey, true);
|
|
274
274
|
this.slot = undefined;
|
|
275
275
|
this.stamp = Number.MAX_SAFE_INTEGER;
|
|
276
276
|
this.context = undefined;
|
|
@@ -388,10 +388,10 @@ function launchNestedNodesThenDoImpl(nodeSlot, error, action) {
|
|
|
388
388
|
var _a;
|
|
389
389
|
const owner = nodeSlot.instance;
|
|
390
390
|
const children = owner.children;
|
|
391
|
-
if (children.
|
|
391
|
+
if (children.isReconciliationInProgress) {
|
|
392
392
|
let promised = undefined;
|
|
393
393
|
try {
|
|
394
|
-
children.
|
|
394
|
+
children.endReconciliation(error);
|
|
395
395
|
for (const child of children.itemsRemoved(true))
|
|
396
396
|
launchFinalizationViaSlot(child, true, true);
|
|
397
397
|
if (!error) {
|
|
@@ -528,7 +528,7 @@ function runScriptNow(nodeSlot) {
|
|
|
528
528
|
try {
|
|
529
529
|
node.stamp++;
|
|
530
530
|
node.numerator = 0;
|
|
531
|
-
node.children.
|
|
531
|
+
node.children.beginReconciliation();
|
|
532
532
|
const driver = node.driver;
|
|
533
533
|
result = driver.runScript(node);
|
|
534
534
|
result = proceedSyncOrAsync(result, v => { launchNestedNodesThenDoImpl(nodeSlot, undefined, NOP); return v; }, e => { console.log(e); launchNestedNodesThenDoImpl(nodeSlot, e !== null && e !== void 0 ? e : new Error("unknown error"), NOP); });
|
|
@@ -1,10 +1,10 @@
|
|
|
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;
|
|
@@ -14,7 +14,7 @@ export type ScriptedListReader<T> = {
|
|
|
14
14
|
isAdded(item: LinkedItem<T>): boolean;
|
|
15
15
|
isMoved(item: LinkedItem<T>): boolean;
|
|
16
16
|
isRemoved(item: LinkedItem<T>): boolean;
|
|
17
|
-
|
|
17
|
+
isFresh(item: LinkedItem<T>): boolean;
|
|
18
18
|
};
|
|
19
19
|
export type LinkedItem<T> = {
|
|
20
20
|
readonly instance: T;
|
|
@@ -23,12 +23,12 @@ export type LinkedItem<T> = {
|
|
|
23
23
|
readonly prev?: LinkedItem<T>;
|
|
24
24
|
aux?: LinkedItem<T>;
|
|
25
25
|
};
|
|
26
|
-
export declare class
|
|
26
|
+
export declare class ReconciliationList<T> implements ReconciliationListReader<T> {
|
|
27
27
|
readonly getKey: GetListItemKey<T>;
|
|
28
28
|
private strict;
|
|
29
29
|
private map;
|
|
30
|
-
private
|
|
31
|
-
private
|
|
30
|
+
private tag;
|
|
31
|
+
private fresh;
|
|
32
32
|
private added;
|
|
33
33
|
private removed;
|
|
34
34
|
private lastNotFoundKey;
|
|
@@ -39,7 +39,7 @@ export declare class ScriptedList<T> implements ScriptedListReader<T> {
|
|
|
39
39
|
get count(): number;
|
|
40
40
|
get countOfAdded(): number;
|
|
41
41
|
get countOfRemoved(): number;
|
|
42
|
-
get
|
|
42
|
+
get isReconciliationInProgress(): boolean;
|
|
43
43
|
lookup(key: string | undefined): LinkedItem<T> | undefined;
|
|
44
44
|
tryReuse(key: string, resolution?: {
|
|
45
45
|
isDuplicate: boolean;
|
|
@@ -47,8 +47,8 @@ export declare class ScriptedList<T> implements ScriptedListReader<T> {
|
|
|
47
47
|
add(instance: T): LinkedItem<T>;
|
|
48
48
|
remove(item: LinkedItem<T>): void;
|
|
49
49
|
move(item: LinkedItem<T>, after: LinkedItem<T>): void;
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
beginReconciliation(): void;
|
|
51
|
+
endReconciliation(error?: unknown): void;
|
|
52
52
|
resetAddedAndRemovedLists(): void;
|
|
53
53
|
firstItem(): LinkedItem<T> | undefined;
|
|
54
54
|
lastItem(): LinkedItem<T> | undefined;
|
|
@@ -58,7 +58,7 @@ export declare class ScriptedList<T> implements ScriptedListReader<T> {
|
|
|
58
58
|
isAdded(item: LinkedItem<T>): boolean;
|
|
59
59
|
isMoved(item: LinkedItem<T>): boolean;
|
|
60
60
|
isRemoved(item: LinkedItem<T>): boolean;
|
|
61
|
-
|
|
61
|
+
isFresh(item: LinkedItem<T>): boolean;
|
|
62
62
|
markAsMoved(item: LinkedItem<T>): void;
|
|
63
63
|
static createItem<T>(instance: T): LinkedItem<T>;
|
|
64
64
|
}
|
|
@@ -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.fresh = 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.fresh.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.fresh.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.status =
|
|
58
|
+
item.status = tag;
|
|
59
59
|
this.strictNextItem = item.next;
|
|
60
60
|
this.removed.exclude(item);
|
|
61
|
-
item.index = this.
|
|
62
|
-
this.
|
|
61
|
+
item.index = this.fresh.count;
|
|
62
|
+
this.fresh.include(item);
|
|
63
63
|
if (resolution)
|
|
64
64
|
resolution.isDuplicate = false;
|
|
65
65
|
}
|
|
@@ -76,55 +76,55 @@ 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
|
-
let
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
this.
|
|
79
|
+
let tag = this.tag;
|
|
80
|
+
if (tag < 0) {
|
|
81
|
+
tag = ~this.tag + 1;
|
|
82
|
+
this.tag = ~tag;
|
|
83
83
|
}
|
|
84
|
-
const item = new LinkedItemImpl(instance,
|
|
84
|
+
const item = new LinkedItemImpl(instance, tag);
|
|
85
85
|
this.map.set(key, item);
|
|
86
86
|
this.lastNotFoundKey = undefined;
|
|
87
87
|
this.strictNextItem = undefined;
|
|
88
|
-
item.index = this.
|
|
89
|
-
this.
|
|
88
|
+
item.index = this.fresh.count;
|
|
89
|
+
this.fresh.include(item);
|
|
90
90
|
this.added.aux(item);
|
|
91
91
|
return item;
|
|
92
92
|
}
|
|
93
93
|
remove(item) {
|
|
94
94
|
const t = item;
|
|
95
95
|
if (!this.isRemoved(t)) {
|
|
96
|
-
this.
|
|
96
|
+
this.fresh.exclude(t);
|
|
97
97
|
this.removed.include(t);
|
|
98
|
-
t.
|
|
98
|
+
t.tag--;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
move(item, after) {
|
|
102
102
|
throw misuse("not implemented");
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
if (this.
|
|
106
|
-
throw misuse("
|
|
107
|
-
this.
|
|
108
|
-
this.strictNextItem = this.
|
|
109
|
-
this.removed.grab(this.
|
|
104
|
+
beginReconciliation() {
|
|
105
|
+
if (this.isReconciliationInProgress)
|
|
106
|
+
throw misuse("reconciliation is in progress already");
|
|
107
|
+
this.tag = ~this.tag + 1;
|
|
108
|
+
this.strictNextItem = this.fresh.first;
|
|
109
|
+
this.removed.grab(this.fresh, false);
|
|
110
110
|
this.added.reset();
|
|
111
111
|
}
|
|
112
|
-
|
|
113
|
-
if (!this.
|
|
114
|
-
throw misuse("
|
|
115
|
-
this.
|
|
112
|
+
endReconciliation(error) {
|
|
113
|
+
if (!this.isReconciliationInProgress)
|
|
114
|
+
throw misuse("reconciliation is ended already");
|
|
115
|
+
this.tag = ~this.tag;
|
|
116
116
|
if (error === undefined) {
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
117
|
+
const freshCount = this.fresh.count;
|
|
118
|
+
if (freshCount > 0) {
|
|
119
119
|
const getKey = this.getKey;
|
|
120
|
-
if (
|
|
120
|
+
if (freshCount > this.removed.count) {
|
|
121
121
|
const map = this.map;
|
|
122
122
|
for (const x of this.removed.items())
|
|
123
123
|
map.delete(getKey(x.instance));
|
|
124
124
|
}
|
|
125
125
|
else {
|
|
126
126
|
const map = this.map = new Map();
|
|
127
|
-
for (const x of this.
|
|
127
|
+
for (const x of this.fresh.items())
|
|
128
128
|
map.set(getKey(x.instance), x);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -132,11 +132,11 @@ export class ScriptedList {
|
|
|
132
132
|
this.map = new Map();
|
|
133
133
|
}
|
|
134
134
|
else {
|
|
135
|
-
this.
|
|
135
|
+
this.fresh.grab(this.removed, true);
|
|
136
136
|
const getKey = this.getKey;
|
|
137
137
|
for (const x of this.added.itemsViaAux()) {
|
|
138
138
|
this.map.delete(getKey(x.instance));
|
|
139
|
-
this.
|
|
139
|
+
this.fresh.exclude(x);
|
|
140
140
|
}
|
|
141
141
|
this.added.reset();
|
|
142
142
|
}
|
|
@@ -146,14 +146,14 @@ export class ScriptedList {
|
|
|
146
146
|
this.added.reset();
|
|
147
147
|
}
|
|
148
148
|
firstItem() {
|
|
149
|
-
return this.
|
|
149
|
+
return this.fresh.first;
|
|
150
150
|
}
|
|
151
151
|
lastItem() {
|
|
152
|
-
return this.
|
|
152
|
+
return this.fresh.last;
|
|
153
153
|
}
|
|
154
154
|
*items(onlyAfter) {
|
|
155
155
|
var _a;
|
|
156
|
-
let x = (_a = onlyAfter === null || onlyAfter === void 0 ? void 0 : onlyAfter.next) !== null && _a !== void 0 ? _a : this.
|
|
156
|
+
let x = (_a = onlyAfter === null || onlyAfter === void 0 ? void 0 : onlyAfter.next) !== null && _a !== void 0 ? _a : this.fresh.first;
|
|
157
157
|
while (x !== undefined) {
|
|
158
158
|
const next = x.next;
|
|
159
159
|
yield x;
|
|
@@ -183,42 +183,42 @@ export class ScriptedList {
|
|
|
183
183
|
}
|
|
184
184
|
isAdded(item) {
|
|
185
185
|
const t = item;
|
|
186
|
-
let
|
|
187
|
-
if (
|
|
188
|
-
|
|
189
|
-
return t.status === ~
|
|
186
|
+
let tag = this.tag;
|
|
187
|
+
if (tag < 0)
|
|
188
|
+
tag = ~tag;
|
|
189
|
+
return t.status === ~tag && t.tag > 0;
|
|
190
190
|
}
|
|
191
191
|
isMoved(item) {
|
|
192
192
|
const t = item;
|
|
193
|
-
let
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
return t.status ===
|
|
193
|
+
let tag = this.tag;
|
|
194
|
+
if (tag < 0)
|
|
195
|
+
tag = ~tag;
|
|
196
|
+
return t.status === tag && t.tag > 0;
|
|
197
197
|
}
|
|
198
198
|
isRemoved(item) {
|
|
199
199
|
const t = item;
|
|
200
|
-
const
|
|
201
|
-
return
|
|
200
|
+
const tag = this.tag;
|
|
201
|
+
return tag > 0 ? t.tag < tag : t.tag < tag - 1;
|
|
202
202
|
}
|
|
203
|
-
|
|
203
|
+
isFresh(item) {
|
|
204
204
|
const t = item;
|
|
205
|
-
return t.
|
|
205
|
+
return t.tag === this.tag;
|
|
206
206
|
}
|
|
207
207
|
markAsMoved(item) {
|
|
208
208
|
const t = item;
|
|
209
|
-
if (t.
|
|
210
|
-
t.status = t.
|
|
209
|
+
if (t.tag > 0)
|
|
210
|
+
t.status = t.tag;
|
|
211
211
|
}
|
|
212
212
|
static createItem(instance) {
|
|
213
213
|
return new LinkedItemImpl(instance, 0);
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
class LinkedItemImpl {
|
|
217
|
-
constructor(instance,
|
|
217
|
+
constructor(instance, tag) {
|
|
218
218
|
this.instance = instance;
|
|
219
219
|
this.index = -1;
|
|
220
|
-
this.
|
|
221
|
-
this.status = ~
|
|
220
|
+
this.tag = tag;
|
|
221
|
+
this.status = ~tag;
|
|
222
222
|
this.next = undefined;
|
|
223
223
|
this.prev = undefined;
|
|
224
224
|
this.aux = undefined;
|