reactronic 0.95.25048 → 0.96.26002
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.
|
@@ -6,16 +6,16 @@ import { RxObject } from "../core/Mvcc.js";
|
|
|
6
6
|
export type Script<E> = (this: E, o: E, basis: () => void) => void;
|
|
7
7
|
export type ScriptAsync<E> = (this: E, o: E, basis: () => Promise<void>) => Promise<void>;
|
|
8
8
|
export type Handler<E = unknown, R = void> = (o: E) => R;
|
|
9
|
-
export declare function declare<E = void>(driver: ReactiveTreeNodeDriver<E>,
|
|
9
|
+
export declare function declare<E = void>(driver: ReactiveTreeNodeDriver<E>, body?: Script<E>, bodyTask?: ScriptAsync<E>, key?: string, mode?: Mode, preparation?: Script<E>, preparationTask?: ScriptAsync<E>, finalization?: Script<E>, signalArgs?: unknown, basis?: ReactiveTreeNodeDecl<E>): ReactiveTreeNode<E>;
|
|
10
10
|
export declare function declare<E = void>(driver: ReactiveTreeNodeDriver<E>, declaration?: ReactiveTreeNodeDecl<E>): ReactiveTreeNode<E>;
|
|
11
|
-
export declare function declare<E = void>(driver: ReactiveTreeNodeDriver<E>,
|
|
11
|
+
export declare function declare<E = void>(driver: ReactiveTreeNodeDriver<E>, bodyOrDeclaration?: Script<E> | ReactiveTreeNodeDecl<E>, bodyTask?: ScriptAsync<E>, key?: string, mode?: Mode, preparation?: Script<E>, preparationTask?: ScriptAsync<E>, finalization?: Script<E>, signalArgs?: unknown, basis?: ReactiveTreeNodeDecl<E>): ReactiveTreeNode<E>;
|
|
12
12
|
export declare function derivative<E = void>(declaration?: ReactiveTreeNodeDecl<E>, basis?: ReactiveTreeNodeDecl<E>): ReactiveTreeNodeDecl<E>;
|
|
13
13
|
export declare function launch<T>(node: ReactiveTreeNode<T>, signalArgs?: unknown): ReactiveTreeNode<T>;
|
|
14
14
|
export declare abstract class ReactiveTreeNode<E = unknown> {
|
|
15
15
|
static readonly shortFrameDuration = 16;
|
|
16
16
|
static readonly longFrameDuration = 300;
|
|
17
17
|
static frameDuration: number;
|
|
18
|
-
static
|
|
18
|
+
static currentBodyPriority: Priority;
|
|
19
19
|
abstract readonly key: string;
|
|
20
20
|
abstract readonly driver: ReactiveTreeNodeDriver<E>;
|
|
21
21
|
abstract readonly declaration: Readonly<ReactiveTreeNodeDecl<E>>;
|
|
@@ -35,8 +35,8 @@ export declare abstract class ReactiveTreeNode<E = unknown> {
|
|
|
35
35
|
abstract has(mode: Mode): boolean;
|
|
36
36
|
abstract configureReactivity(options: Partial<ReactivityOptions>): ReactivityOptions;
|
|
37
37
|
static get current(): ReactiveTreeNode;
|
|
38
|
-
static get
|
|
39
|
-
static
|
|
38
|
+
static get isFirstBodyBuild(): boolean;
|
|
39
|
+
static buildBody(node: ReactiveTreeNode<any>, signalArgs: unknown): void;
|
|
40
40
|
static launchFinalization(node: ReactiveTreeNode<any>): void;
|
|
41
41
|
static launchNestedNodesThenDo(action: (error: unknown) => void): void;
|
|
42
42
|
static markAsMounted(node: ReactiveTreeNode<any>, yes: boolean): void;
|
|
@@ -48,12 +48,12 @@ export declare abstract class ReactiveTreeNode<E = unknown> {
|
|
|
48
48
|
static setDefaultLoggingOptions(logging?: LoggingOptions): void;
|
|
49
49
|
}
|
|
50
50
|
export type ReactiveTreeNodeDecl<E = unknown> = {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
body?: Script<E>;
|
|
52
|
+
bodyTask?: ScriptAsync<E>;
|
|
53
53
|
key?: string;
|
|
54
54
|
mode?: Mode;
|
|
55
55
|
preparation?: Script<E>;
|
|
56
|
-
|
|
56
|
+
preparationTask?: ScriptAsync<E>;
|
|
57
57
|
finalization?: Script<E>;
|
|
58
58
|
signalArgs?: unknown;
|
|
59
59
|
basis?: ReactiveTreeNodeDecl<E>;
|
|
@@ -66,7 +66,7 @@ export type ReactiveTreeNodeDriver<E = unknown> = {
|
|
|
66
66
|
runPreparation(node: ReactiveTreeNode<E>): void;
|
|
67
67
|
runFinalization(node: ReactiveTreeNode<E>, isLeader: boolean): boolean;
|
|
68
68
|
runMount(node: ReactiveTreeNode<E>): void;
|
|
69
|
-
|
|
69
|
+
buildBody(node: ReactiveTreeNode<E>): void | Promise<void>;
|
|
70
70
|
declareChild(ownerNode: ReactiveTreeNode<E>, childDriver: ReactiveTreeNodeDriver<any>, childDeclaration?: ReactiveTreeNodeDecl<any>, childBasis?: ReactiveTreeNodeDecl<any>): LinkedItem<ReactiveTreeNode> | undefined;
|
|
71
71
|
provideHost(node: ReactiveTreeNode<E>): ReactiveTreeNode<E>;
|
|
72
72
|
};
|
|
@@ -82,7 +82,7 @@ export declare abstract class BaseDriver<E = unknown> implements ReactiveTreeNod
|
|
|
82
82
|
runPreparation(node: ReactiveTreeNode<E>): void | Promise<void>;
|
|
83
83
|
runFinalization(node: ReactiveTreeNode<E>, isLeader: boolean): boolean;
|
|
84
84
|
runMount(node: ReactiveTreeNode<E>): void;
|
|
85
|
-
|
|
85
|
+
buildBody(node: ReactiveTreeNode<E>): void | Promise<void>;
|
|
86
86
|
declareChild(ownerNode: ReactiveTreeNode<E>, childDriver: ReactiveTreeNodeDriver<any>, childDeclaration?: ReactiveTreeNodeDecl<any>, childBasis?: ReactiveTreeNodeDecl<any>): LinkedItem<ReactiveTreeNode> | undefined;
|
|
87
87
|
provideHost(node: ReactiveTreeNode<E>): ReactiveTreeNode<E>;
|
|
88
88
|
}
|
|
@@ -126,7 +126,7 @@ declare class ReactiveTreeNode$<E = unknown> extends ReactiveTreeNode<E> {
|
|
|
126
126
|
set strictOrder(value: boolean);
|
|
127
127
|
get isMoved(): boolean;
|
|
128
128
|
has(mode: Mode): boolean;
|
|
129
|
-
|
|
129
|
+
body(_signalArgs: unknown): void;
|
|
130
130
|
configureReactivity(options: Partial<ReactivityOptions>): ReactivityOptions;
|
|
131
131
|
static get nodeSlot(): LinkedItem<ReactiveTreeNode$>;
|
|
132
132
|
static tryUseTreeVariableValue<T extends Object>(variable: ReactiveTreeVariable<T>): T | undefined;
|
|
@@ -24,23 +24,23 @@ import { Priority, Mode, Isolation, Reentrance } from "../Enums.js";
|
|
|
24
24
|
import { RxObject } from "../core/Mvcc.js";
|
|
25
25
|
import { Transaction } from "../core/Transaction.js";
|
|
26
26
|
import { ReactiveSystem, options, signal, reaction, runTransactional, runNonReactive, manageReaction, disposeRxObject } from "../System.js";
|
|
27
|
-
export function declare(driver,
|
|
27
|
+
export function declare(driver, bodyOrDeclaration, bodyTask, key, mode, preparation, preparationTask, finalization, signalArgs, basis) {
|
|
28
28
|
let result;
|
|
29
29
|
let declaration;
|
|
30
|
-
if (
|
|
30
|
+
if (bodyOrDeclaration instanceof Function) {
|
|
31
31
|
declaration = {
|
|
32
|
-
|
|
33
|
-
preparation,
|
|
32
|
+
body: bodyOrDeclaration, bodyTask, key, mode,
|
|
33
|
+
preparation, preparationTask, finalization, signalArgs, basis,
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
else
|
|
37
|
-
declaration =
|
|
37
|
+
declaration = bodyOrDeclaration !== null && bodyOrDeclaration !== void 0 ? bodyOrDeclaration : {};
|
|
38
38
|
let effectiveKey = declaration.key;
|
|
39
39
|
const owner = gNodeSlot === null || gNodeSlot === void 0 ? void 0 : gNodeSlot.instance;
|
|
40
40
|
if (owner) {
|
|
41
41
|
let existing = owner.driver.declareChild(owner, driver, declaration, declaration.basis);
|
|
42
42
|
const children = owner.children;
|
|
43
|
-
existing !== null && existing !== void 0 ? existing : (existing = children.tryReuse(effectiveKey = effectiveKey || generateKey(owner), undefined, "nested elements can be declared inside '
|
|
43
|
+
existing !== null && existing !== void 0 ? existing : (existing = children.tryReuse(effectiveKey = effectiveKey || generateKey(owner), undefined, "nested elements can be declared inside 'body' only"));
|
|
44
44
|
if (existing) {
|
|
45
45
|
result = existing.instance;
|
|
46
46
|
if (result.driver !== driver && driver !== undefined)
|
|
@@ -69,22 +69,22 @@ export function derivative(declaration, basis) {
|
|
|
69
69
|
return declaration;
|
|
70
70
|
}
|
|
71
71
|
export function launch(node, signalArgs) {
|
|
72
|
-
ReactiveTreeNode.
|
|
72
|
+
ReactiveTreeNode.buildBody(node, signalArgs);
|
|
73
73
|
return node;
|
|
74
74
|
}
|
|
75
75
|
export class ReactiveTreeNode {
|
|
76
76
|
static get current() {
|
|
77
77
|
return ReactiveTreeNode$.nodeSlot.instance;
|
|
78
78
|
}
|
|
79
|
-
static get
|
|
79
|
+
static get isFirstBodyBuild() {
|
|
80
80
|
return ReactiveTreeNode.current.stamp === 1;
|
|
81
81
|
}
|
|
82
|
-
static
|
|
82
|
+
static buildBody(node, signalArgs) {
|
|
83
83
|
const impl = node;
|
|
84
84
|
const declaration = impl.declaration;
|
|
85
85
|
if (node.stamp >= Number.MAX_SAFE_INTEGER || !signalsAreEqual(signalArgs, declaration.signalArgs)) {
|
|
86
86
|
declaration.signalArgs = signalArgs;
|
|
87
|
-
|
|
87
|
+
buildBodyViaSlot(impl.slot);
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
static launchFinalization(node) {
|
|
@@ -140,7 +140,7 @@ export class ReactiveTreeNode {
|
|
|
140
140
|
ReactiveTreeNode.shortFrameDuration = 16;
|
|
141
141
|
ReactiveTreeNode.longFrameDuration = 300;
|
|
142
142
|
ReactiveTreeNode.frameDuration = ReactiveTreeNode.longFrameDuration;
|
|
143
|
-
ReactiveTreeNode.
|
|
143
|
+
ReactiveTreeNode.currentBodyPriority = Priority.realtime;
|
|
144
144
|
export class BaseDriver {
|
|
145
145
|
constructor(name, isPartition, initialize) {
|
|
146
146
|
this.name = name;
|
|
@@ -158,8 +158,8 @@ export class BaseDriver {
|
|
|
158
158
|
}
|
|
159
159
|
runMount(node) {
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
return
|
|
161
|
+
buildBody(node) {
|
|
162
|
+
return invokeBuildBodyUsingBasisChain(node.element, node.declaration);
|
|
163
163
|
}
|
|
164
164
|
declareChild(ownerNode, childDriver, childDeclaration, childBasis) {
|
|
165
165
|
return undefined;
|
|
@@ -196,32 +196,32 @@ export function getModeUsingBasisChain(declaration) {
|
|
|
196
196
|
var _a;
|
|
197
197
|
return (_a = declaration === null || declaration === void 0 ? void 0 : declaration.mode) !== null && _a !== void 0 ? _a : ((declaration === null || declaration === void 0 ? void 0 : declaration.basis) ? getModeUsingBasisChain(declaration === null || declaration === void 0 ? void 0 : declaration.basis) : Mode.default);
|
|
198
198
|
}
|
|
199
|
-
function
|
|
199
|
+
function invokeBuildBodyUsingBasisChain(element, declaration) {
|
|
200
200
|
let result = undefined;
|
|
201
201
|
const basis = declaration.basis;
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
if (
|
|
205
|
-
throw misuse("'
|
|
206
|
-
if (
|
|
207
|
-
result =
|
|
208
|
-
else if (
|
|
209
|
-
result =
|
|
202
|
+
const body = declaration.body;
|
|
203
|
+
const bodyTask = declaration.bodyTask;
|
|
204
|
+
if (body && bodyTask)
|
|
205
|
+
throw misuse("'body' and 'bodyTask' cannot be defined together");
|
|
206
|
+
if (body)
|
|
207
|
+
result = body.call(element, element, basis ? () => invokeBuildBodyUsingBasisChain(element, basis) : NOP);
|
|
208
|
+
else if (bodyTask)
|
|
209
|
+
result = bodyTask.call(element, element, basis ? () => invokeBuildBodyUsingBasisChain(element, basis) : NOP_ASYNC);
|
|
210
210
|
else if (basis)
|
|
211
|
-
result =
|
|
211
|
+
result = invokeBuildBodyUsingBasisChain(element, basis);
|
|
212
212
|
return result;
|
|
213
213
|
}
|
|
214
214
|
function invokePreparationUsingBasisChain(element, declaration) {
|
|
215
215
|
let result = undefined;
|
|
216
216
|
const basis = declaration.basis;
|
|
217
217
|
const preparation = declaration.preparation;
|
|
218
|
-
const
|
|
219
|
-
if (preparation &&
|
|
220
|
-
throw misuse("'preparation' and '
|
|
218
|
+
const preparationTask = declaration.preparationTask;
|
|
219
|
+
if (preparation && preparationTask)
|
|
220
|
+
throw misuse("'preparation' and 'preparationTask' cannot be defined together");
|
|
221
221
|
if (preparation)
|
|
222
222
|
result = preparation.call(element, element, basis ? () => invokePreparationUsingBasisChain(element, basis) : NOP);
|
|
223
|
-
else if (
|
|
224
|
-
result =
|
|
223
|
+
else if (preparationTask)
|
|
224
|
+
result = preparationTask.call(element, element, basis ? () => invokePreparationUsingBasisChain(element, basis) : NOP_ASYNC);
|
|
225
225
|
else if (basis)
|
|
226
226
|
result = invokePreparationUsingBasisChain(element, basis);
|
|
227
227
|
return result;
|
|
@@ -303,13 +303,13 @@ class ReactiveTreeNode$ extends ReactiveTreeNode {
|
|
|
303
303
|
has(mode) {
|
|
304
304
|
return flags(getModeUsingBasisChain(this.declaration), mode);
|
|
305
305
|
}
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
body(_signalArgs) {
|
|
307
|
+
buildBodyNow(this.slot);
|
|
308
308
|
}
|
|
309
309
|
configureReactivity(options) {
|
|
310
310
|
if (this.stamp < Number.MAX_SAFE_INTEGER - 1 || !this.has(Mode.autonomous))
|
|
311
311
|
throw misuse("reactronic can be configured only for elements with autonomous mode and only during preparation");
|
|
312
|
-
return manageReaction(this.
|
|
312
|
+
return manageReaction(this.body).configure(options);
|
|
313
313
|
}
|
|
314
314
|
static get nodeSlot() {
|
|
315
315
|
if (!gNodeSlot)
|
|
@@ -369,7 +369,7 @@ __decorate([
|
|
|
369
369
|
__metadata("design:type", Function),
|
|
370
370
|
__metadata("design:paramtypes", [Object]),
|
|
371
371
|
__metadata("design:returntype", void 0)
|
|
372
|
-
], ReactiveTreeNode$.prototype, "
|
|
372
|
+
], ReactiveTreeNode$.prototype, "body", null);
|
|
373
373
|
function gatherAuthorityAndPath(node, path, relativeTo) {
|
|
374
374
|
let authority;
|
|
375
375
|
if (node.owner !== node && node.owner !== relativeTo) {
|
|
@@ -409,7 +409,7 @@ function launchNestedNodesThenDoImpl(nodeSlot, error, action) {
|
|
|
409
409
|
mounting = markToMountIfNecessary(mounting, host, child, children, sequential);
|
|
410
410
|
const p = (_a = childNode.priority) !== null && _a !== void 0 ? _a : Priority.realtime;
|
|
411
411
|
if (p === Priority.realtime)
|
|
412
|
-
|
|
412
|
+
buildBodyViaSlot(child);
|
|
413
413
|
else if (p === Priority.normal)
|
|
414
414
|
p1 = push(child, p1);
|
|
415
415
|
else
|
|
@@ -418,7 +418,7 @@ function launchNestedNodesThenDoImpl(nodeSlot, error, action) {
|
|
|
418
418
|
partition = childNode;
|
|
419
419
|
}
|
|
420
420
|
if (!Transaction.isCanceled && (p1 !== undefined || p2 !== undefined))
|
|
421
|
-
promised =
|
|
421
|
+
promised = startIncrementalNestedBodyBuild(nodeSlot, children, p1, p2).then(() => action(error), e => action(e));
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
finally {
|
|
@@ -441,34 +441,34 @@ function markToMountIfNecessary(mounting, host, nodeSlot, children, sequential)
|
|
|
441
441
|
node.host = host;
|
|
442
442
|
return mounting;
|
|
443
443
|
}
|
|
444
|
-
function
|
|
444
|
+
function startIncrementalNestedBodyBuild(ownerSlot, allChildren, priority1, priority2) {
|
|
445
445
|
return __awaiter(this, void 0, void 0, function* () {
|
|
446
446
|
const stamp = ownerSlot.instance.stamp;
|
|
447
447
|
if (priority1)
|
|
448
|
-
yield
|
|
448
|
+
yield runNestedBodyBuildIncrementally(ownerSlot, stamp, allChildren, priority1, Priority.normal);
|
|
449
449
|
if (priority2)
|
|
450
|
-
yield
|
|
450
|
+
yield runNestedBodyBuildIncrementally(ownerSlot, stamp, allChildren, priority2, Priority.background);
|
|
451
451
|
});
|
|
452
452
|
}
|
|
453
|
-
function
|
|
453
|
+
function runNestedBodyBuildIncrementally(owner, stamp, allChildren, items, priority) {
|
|
454
454
|
return __awaiter(this, void 0, void 0, function* () {
|
|
455
455
|
yield Transaction.requestNextFrame();
|
|
456
456
|
const node = owner.instance;
|
|
457
457
|
if (!Transaction.isCanceled || !Transaction.isFrameOver(1, ReactiveTreeNode$.shortFrameDuration / 3)) {
|
|
458
|
-
let outerPriority = ReactiveTreeNode$.
|
|
459
|
-
ReactiveTreeNode$.
|
|
458
|
+
let outerPriority = ReactiveTreeNode$.currentBodyPriority;
|
|
459
|
+
ReactiveTreeNode$.currentBodyPriority = priority;
|
|
460
460
|
try {
|
|
461
461
|
if (node.childrenShuffling)
|
|
462
462
|
shuffle(items);
|
|
463
463
|
const frameDurationLimit = priority === Priority.background ? ReactiveTreeNode.shortFrameDuration : Infinity;
|
|
464
464
|
let frameDuration = Math.min(frameDurationLimit, Math.max(ReactiveTreeNode.frameDuration / 4, ReactiveTreeNode.shortFrameDuration));
|
|
465
465
|
for (const child of items) {
|
|
466
|
-
|
|
466
|
+
buildBodyViaSlot(child);
|
|
467
467
|
if (Transaction.isFrameOver(1, frameDuration)) {
|
|
468
|
-
ReactiveTreeNode$.
|
|
468
|
+
ReactiveTreeNode$.currentBodyPriority = outerPriority;
|
|
469
469
|
yield Transaction.requestNextFrame(0);
|
|
470
|
-
outerPriority = ReactiveTreeNode$.
|
|
471
|
-
ReactiveTreeNode$.
|
|
470
|
+
outerPriority = ReactiveTreeNode$.currentBodyPriority;
|
|
471
|
+
ReactiveTreeNode$.currentBodyPriority = priority;
|
|
472
472
|
frameDuration = Math.min(4 * frameDuration, Math.min(frameDurationLimit, ReactiveTreeNode.frameDuration));
|
|
473
473
|
}
|
|
474
474
|
if (Transaction.isCanceled && Transaction.isFrameOver(1, ReactiveTreeNode.shortFrameDuration / 3))
|
|
@@ -476,12 +476,12 @@ function runNestedScriptsIncrementally(owner, stamp, allChildren, items, priorit
|
|
|
476
476
|
}
|
|
477
477
|
}
|
|
478
478
|
finally {
|
|
479
|
-
ReactiveTreeNode$.
|
|
479
|
+
ReactiveTreeNode$.currentBodyPriority = outerPriority;
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
});
|
|
483
483
|
}
|
|
484
|
-
function
|
|
484
|
+
function buildBodyViaSlot(nodeSlot) {
|
|
485
485
|
const node = nodeSlot.instance;
|
|
486
486
|
if (node.stamp >= 0) {
|
|
487
487
|
if (node.has(Mode.autonomous)) {
|
|
@@ -489,17 +489,17 @@ function launchScriptViaSlot(nodeSlot) {
|
|
|
489
489
|
Transaction.outside(() => {
|
|
490
490
|
if (ReactiveSystem.isLogging)
|
|
491
491
|
ReactiveSystem.setLoggingHint(node.element, node.key);
|
|
492
|
-
manageReaction(node.
|
|
492
|
+
manageReaction(node.body).configure({
|
|
493
493
|
order: node.level,
|
|
494
494
|
});
|
|
495
495
|
});
|
|
496
496
|
}
|
|
497
|
-
runNonReactive(node.
|
|
497
|
+
runNonReactive(node.body, node.declaration.signalArgs);
|
|
498
498
|
}
|
|
499
499
|
else if (node.owner !== node)
|
|
500
|
-
|
|
500
|
+
buildBodyNow(nodeSlot);
|
|
501
501
|
else
|
|
502
|
-
runTransactional(() =>
|
|
502
|
+
runTransactional(() => buildBodyNow(nodeSlot));
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
function mountOrRemountIfNecessary(node) {
|
|
@@ -518,7 +518,7 @@ function mountOrRemountIfNecessary(node) {
|
|
|
518
518
|
else if (node.isMoved && !node.has(Mode.external) && node.host !== node)
|
|
519
519
|
runNonReactive(() => driver.runMount(node));
|
|
520
520
|
}
|
|
521
|
-
function
|
|
521
|
+
function buildBodyNow(nodeSlot) {
|
|
522
522
|
const node = nodeSlot.instance;
|
|
523
523
|
if (node.stamp >= 0) {
|
|
524
524
|
let result = undefined;
|
|
@@ -530,12 +530,12 @@ function runScriptNow(nodeSlot) {
|
|
|
530
530
|
node.numerator = 0;
|
|
531
531
|
node.children.beginReconciliation();
|
|
532
532
|
const driver = node.driver;
|
|
533
|
-
result = driver.
|
|
533
|
+
result = driver.buildBody(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); });
|
|
535
535
|
}
|
|
536
536
|
catch (e) {
|
|
537
537
|
launchNestedNodesThenDoImpl(nodeSlot, e, NOP);
|
|
538
|
-
console.log(`Reactive node
|
|
538
|
+
console.log(`Reactive node body build failed: ${node.key}`);
|
|
539
539
|
console.log(`${e}`);
|
|
540
540
|
}
|
|
541
541
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type Extractor<T, Result> = (item: T) => Result;
|
|
2
2
|
export type KeyExtractor<T> = Extractor<T, string | undefined>;
|
|
3
3
|
export declare class LinkedList<T extends LinkedItem<T>> {
|
|
4
|
-
readonly
|
|
4
|
+
readonly keyExtractor: KeyExtractor<T>;
|
|
5
5
|
private isStrictOrder$;
|
|
6
6
|
private map;
|
|
7
7
|
items$: LinkedSubList<T>;
|
|
@@ -13,18 +13,20 @@ export declare class LinkedList<T extends LinkedItem<T>> {
|
|
|
13
13
|
get isRenovationInProgress(): boolean;
|
|
14
14
|
get count(): number;
|
|
15
15
|
items(): Generator<T>;
|
|
16
|
-
|
|
16
|
+
tryLookup(key: string): T | undefined;
|
|
17
|
+
lookup(key: string): T;
|
|
17
18
|
add(item: T, before?: T): void;
|
|
18
19
|
move(item: T, before: T | undefined): void;
|
|
19
20
|
remove(item: T): void;
|
|
20
21
|
beginRenovation(diff?: Array<T>): LinkedListRenovation<T>;
|
|
21
22
|
endRenovation(error?: unknown): LinkedListRenovation<T>;
|
|
23
|
+
extractKey(item: T): string;
|
|
22
24
|
static move$<T extends LinkedItem<T>>(list: LinkedList<T>, item: T, before: T | undefined): void;
|
|
23
25
|
static remove$<T extends LinkedItem<T>>(list: LinkedList<T>, item: T): void;
|
|
24
|
-
static removeKey$<T extends LinkedItem<T>>(list: LinkedList<T>, key: string
|
|
26
|
+
static removeKey$<T extends LinkedItem<T>>(list: LinkedList<T>, key: string): void;
|
|
25
27
|
}
|
|
26
28
|
export declare enum Mark {
|
|
27
|
-
|
|
29
|
+
reaffirmed = 0,
|
|
28
30
|
added = 1,
|
|
29
31
|
modified = 2,
|
|
30
32
|
removed = 3
|
|
@@ -60,8 +62,8 @@ export declare class LinkedListRenovation<T extends LinkedItem<T>> {
|
|
|
60
62
|
private expected;
|
|
61
63
|
private absent;
|
|
62
64
|
constructor(list: LinkedList<T>, former: LinkedSubList<T>, diff?: Array<T>);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
tryLookup(key: string): T | undefined;
|
|
66
|
+
tryReaffirm(key: string, resolution?: {
|
|
65
67
|
isDuplicate: boolean;
|
|
66
68
|
}, error?: string): T | undefined;
|
|
67
69
|
thisIsAdded(item: T, before?: T): T;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { misuse } from "./Dbg.js";
|
|
2
2
|
export class LinkedList {
|
|
3
3
|
constructor(keyExtractor, isStrictOrder = false) {
|
|
4
|
-
this.
|
|
4
|
+
this.keyExtractor = keyExtractor;
|
|
5
5
|
this.isStrictOrder$ = isStrictOrder;
|
|
6
6
|
this.map = new Map();
|
|
7
7
|
this.items$ = new LinkedSubList();
|
|
@@ -29,11 +29,17 @@ export class LinkedList {
|
|
|
29
29
|
items() {
|
|
30
30
|
return this.items$.items();
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
tryLookup(key) {
|
|
33
33
|
return this.map.get(key);
|
|
34
34
|
}
|
|
35
|
+
lookup(key) {
|
|
36
|
+
const result = this.tryLookup(key);
|
|
37
|
+
if (result === undefined)
|
|
38
|
+
throw misuse(`item with given key doesn't exist: ${key}`);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
35
41
|
add(item, before) {
|
|
36
|
-
const key = this.
|
|
42
|
+
const key = this.extractKey(item);
|
|
37
43
|
if (this.map.get(key) !== undefined)
|
|
38
44
|
throw misuse(`item with given key already exists: ${key}`);
|
|
39
45
|
this.map.set(key, item);
|
|
@@ -70,7 +76,7 @@ export class LinkedList {
|
|
|
70
76
|
if (error === undefined) {
|
|
71
77
|
for (const x of renovation.lostItems()) {
|
|
72
78
|
if (!x.isManagedExternally) {
|
|
73
|
-
LinkedList.removeKey$(this, this.
|
|
79
|
+
LinkedList.removeKey$(this, this.extractKey(x));
|
|
74
80
|
LinkedItem.setStatus$(x, Mark.removed, 0);
|
|
75
81
|
}
|
|
76
82
|
else
|
|
@@ -80,17 +86,24 @@ export class LinkedList {
|
|
|
80
86
|
else {
|
|
81
87
|
for (const x of renovation.lostItems()) {
|
|
82
88
|
LinkedItem.link$(items, x, undefined);
|
|
83
|
-
LinkedItem.setStatus$(x, Mark.
|
|
89
|
+
LinkedItem.setStatus$(x, Mark.reaffirmed, items.count);
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
this.renovation$ = undefined;
|
|
87
93
|
return renovation;
|
|
88
94
|
}
|
|
95
|
+
extractKey(item) {
|
|
96
|
+
const result = this.keyExtractor(item);
|
|
97
|
+
if (result === undefined)
|
|
98
|
+
throw misuse("given item has no key");
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
89
101
|
static move$(list, item, before) {
|
|
90
102
|
LinkedItem.link$(list.items$, item, before);
|
|
91
103
|
}
|
|
92
104
|
static remove$(list, item) {
|
|
93
|
-
|
|
105
|
+
const key = list.extractKey(item);
|
|
106
|
+
LinkedList.removeKey$(list, key);
|
|
94
107
|
LinkedItem.link$(undefined, item, undefined);
|
|
95
108
|
}
|
|
96
109
|
static removeKey$(list, key) {
|
|
@@ -99,7 +112,7 @@ export class LinkedList {
|
|
|
99
112
|
}
|
|
100
113
|
export var Mark;
|
|
101
114
|
(function (Mark) {
|
|
102
|
-
Mark[Mark["
|
|
115
|
+
Mark[Mark["reaffirmed"] = 0] = "reaffirmed";
|
|
103
116
|
Mark[Mark["added"] = 1] = "added";
|
|
104
117
|
Mark[Mark["modified"] = 2] = "modified";
|
|
105
118
|
Mark[Mark["removed"] = 3] = "removed";
|
|
@@ -222,12 +235,12 @@ export class LinkedListRenovation {
|
|
|
222
235
|
this.expected = former.first;
|
|
223
236
|
this.absent = undefined;
|
|
224
237
|
}
|
|
225
|
-
|
|
238
|
+
tryLookup(key) {
|
|
226
239
|
let result = undefined;
|
|
227
240
|
if (key !== undefined && key !== this.absent) {
|
|
228
|
-
result = this.list.
|
|
241
|
+
result = this.list.tryLookup(key);
|
|
229
242
|
if (result !== undefined) {
|
|
230
|
-
if (this.list.
|
|
243
|
+
if (this.list.keyExtractor(result) !== key) {
|
|
231
244
|
this.absent = key;
|
|
232
245
|
result = undefined;
|
|
233
246
|
}
|
|
@@ -237,14 +250,14 @@ export class LinkedListRenovation {
|
|
|
237
250
|
}
|
|
238
251
|
return result;
|
|
239
252
|
}
|
|
240
|
-
|
|
253
|
+
tryReaffirm(key, resolution, error) {
|
|
241
254
|
var _a, _b;
|
|
242
255
|
const list = this.list;
|
|
243
256
|
if (!list.isRenovationInProgress)
|
|
244
257
|
throw misuse(error !== null && error !== void 0 ? error : "renovation is no longer in progress");
|
|
245
258
|
let x = this.expected;
|
|
246
|
-
if (key !== (x ? list.
|
|
247
|
-
x = this.
|
|
259
|
+
if (key !== (x ? list.keyExtractor(x) : undefined))
|
|
260
|
+
x = this.tryLookup(key);
|
|
248
261
|
if (x !== undefined) {
|
|
249
262
|
const result = this.list.items$;
|
|
250
263
|
if (x.list !== result) {
|
|
@@ -256,7 +269,7 @@ export class LinkedListRenovation {
|
|
|
256
269
|
(_b = this.diff) === null || _b === void 0 ? void 0 : _b.push(x);
|
|
257
270
|
}
|
|
258
271
|
else
|
|
259
|
-
LinkedItem.setStatus$(x, Mark.
|
|
272
|
+
LinkedItem.setStatus$(x, Mark.reaffirmed, result.count);
|
|
260
273
|
this.expected = next;
|
|
261
274
|
if (resolution)
|
|
262
275
|
resolution.isDuplicate = false;
|
|
@@ -281,9 +294,9 @@ export class LinkedListRenovation {
|
|
|
281
294
|
}
|
|
282
295
|
thisIsModified(item) {
|
|
283
296
|
if (item.list !== this.list.items$)
|
|
284
|
-
throw misuse("only
|
|
297
|
+
throw misuse("only reaffirmed items can be marked as modified");
|
|
285
298
|
const m = item.mark;
|
|
286
|
-
if (m === Mark.
|
|
299
|
+
if (m === Mark.reaffirmed)
|
|
287
300
|
LinkedItem.setStatus$(item, Mark.modified, item.rank);
|
|
288
301
|
else if (m !== Mark.modified)
|
|
289
302
|
throw misuse("item is renovated already and cannot be marked as modified");
|