doxum 0.1.33 → 0.1.34
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 +6 -7
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.js +1 -1
- package/dist/index.cjs +340 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +340 -124
- package/dist/index.js.map +1 -1
- package/dist/{transform-CSPGdBe5.cjs → transform-Bt1Mwgrj.cjs} +140 -157
- package/dist/transform-Bt1Mwgrj.cjs.map +1 -0
- package/dist/{transform-A9Lx5R2l.js → transform-RghG_Qxs.js} +141 -152
- package/dist/transform-RghG_Qxs.js.map +1 -0
- package/package.json +1 -1
- package/skills/doxum-runtime/SKILL.md +1 -1
- package/skills/doxum-runtime/references/integrations.md +2 -2
- package/skills/doxum-runtime/references/invariants.md +6 -3
- package/skills/doxum-runtime/references/projections.md +21 -20
- package/skills/doxum-runtime/references/public-api.md +3 -7
- package/skills/doxum-runtime/references/recipes.md +2 -2
- package/dist/transform-A9Lx5R2l.js.map +0 -1
- package/dist/transform-CSPGdBe5.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_transform = require("./transform-
|
|
2
|
+
const require_transform = require("./transform-Bt1Mwgrj.cjs");
|
|
3
3
|
const require_record = require("./record-ChYUi8PP.cjs");
|
|
4
4
|
const require_driver = require("./driver-CN3dGxQI.cjs");
|
|
5
5
|
//#region core/src/schema/model.ts
|
|
@@ -3618,6 +3618,104 @@ function createValueDerive(dependencies, compute, equality = Object.is) {
|
|
|
3618
3618
|
}
|
|
3619
3619
|
const derive = Object.assign(createValueDerive, { keyed: keyedDerive });
|
|
3620
3620
|
//#endregion
|
|
3621
|
+
//#region core/src/projection/collection/changes.ts
|
|
3622
|
+
/** Net transitions for one consumer's unconsumed interval; bounded by touched keys. */
|
|
3623
|
+
const createCollectionChanges = () => {
|
|
3624
|
+
let first;
|
|
3625
|
+
let beforeOrder = [];
|
|
3626
|
+
let afterOrder = [];
|
|
3627
|
+
let cached;
|
|
3628
|
+
let valid = false;
|
|
3629
|
+
let transitions;
|
|
3630
|
+
const merge = (change) => {
|
|
3631
|
+
const write = (key, before, after) => {
|
|
3632
|
+
const previous = transitions.get(key);
|
|
3633
|
+
const initial = previous?.before ?? before;
|
|
3634
|
+
if (initial.present === after.present && (!initial.present || after.present && Object.is(initial.value, after.value))) transitions.delete(key);
|
|
3635
|
+
else if (previous) previous.after = after;
|
|
3636
|
+
else transitions.set(key, {
|
|
3637
|
+
before,
|
|
3638
|
+
after
|
|
3639
|
+
});
|
|
3640
|
+
};
|
|
3641
|
+
for (const entry of change.added) write(entry.key, { present: false }, {
|
|
3642
|
+
present: true,
|
|
3643
|
+
value: entry.after
|
|
3644
|
+
});
|
|
3645
|
+
for (const entry of change.updated) write(entry.key, {
|
|
3646
|
+
present: true,
|
|
3647
|
+
value: entry.before
|
|
3648
|
+
}, {
|
|
3649
|
+
present: true,
|
|
3650
|
+
value: entry.after
|
|
3651
|
+
});
|
|
3652
|
+
for (const entry of change.removed) write(entry.key, {
|
|
3653
|
+
present: true,
|
|
3654
|
+
value: entry.before
|
|
3655
|
+
}, { present: false });
|
|
3656
|
+
};
|
|
3657
|
+
return {
|
|
3658
|
+
add(change, before, after) {
|
|
3659
|
+
valid = false;
|
|
3660
|
+
afterOrder = after;
|
|
3661
|
+
if (!first) {
|
|
3662
|
+
first = change;
|
|
3663
|
+
beforeOrder = before;
|
|
3664
|
+
return;
|
|
3665
|
+
}
|
|
3666
|
+
if (first.kind === "reset") return;
|
|
3667
|
+
if (change.kind === "reset") {
|
|
3668
|
+
first = change;
|
|
3669
|
+
transitions = void 0;
|
|
3670
|
+
return;
|
|
3671
|
+
}
|
|
3672
|
+
if (!transitions) {
|
|
3673
|
+
transitions = /* @__PURE__ */ new Map();
|
|
3674
|
+
merge(first);
|
|
3675
|
+
}
|
|
3676
|
+
merge(change);
|
|
3677
|
+
},
|
|
3678
|
+
current() {
|
|
3679
|
+
if (!transitions) return first;
|
|
3680
|
+
if (valid) return cached;
|
|
3681
|
+
const added = [];
|
|
3682
|
+
const updated = [];
|
|
3683
|
+
const removed = [];
|
|
3684
|
+
for (const [key, { before, after }] of transitions) if (!before.present) {
|
|
3685
|
+
if (after.present) added.push({
|
|
3686
|
+
key,
|
|
3687
|
+
after: after.value
|
|
3688
|
+
});
|
|
3689
|
+
} else if (!after.present) removed.push({
|
|
3690
|
+
key,
|
|
3691
|
+
before: before.value
|
|
3692
|
+
});
|
|
3693
|
+
else if (!Object.is(before.value, after.value)) updated.push({
|
|
3694
|
+
key,
|
|
3695
|
+
before: before.value,
|
|
3696
|
+
after: after.value
|
|
3697
|
+
});
|
|
3698
|
+
cached = require_transform.createCollectionChange({
|
|
3699
|
+
added,
|
|
3700
|
+
updated,
|
|
3701
|
+
removed,
|
|
3702
|
+
beforeOrder,
|
|
3703
|
+
afterOrder
|
|
3704
|
+
});
|
|
3705
|
+
valid = true;
|
|
3706
|
+
return cached;
|
|
3707
|
+
},
|
|
3708
|
+
reset: () => first?.kind === "reset",
|
|
3709
|
+
clear() {
|
|
3710
|
+
first = void 0;
|
|
3711
|
+
cached = void 0;
|
|
3712
|
+
valid = false;
|
|
3713
|
+
transitions = void 0;
|
|
3714
|
+
beforeOrder = afterOrder = [];
|
|
3715
|
+
}
|
|
3716
|
+
};
|
|
3717
|
+
};
|
|
3718
|
+
//#endregion
|
|
3621
3719
|
//#region core/src/projection/collection/index.ts
|
|
3622
3720
|
const height = (node) => node?.height ?? 0;
|
|
3623
3721
|
const node = (key, value, left, right) => {
|
|
@@ -3712,7 +3810,7 @@ var PersistentKeyedIndex = class PersistentKeyedIndex {
|
|
|
3712
3810
|
const createCollectionState = (initial) => {
|
|
3713
3811
|
const values = new Map(initial);
|
|
3714
3812
|
let ids = Object.freeze([...values.keys()]);
|
|
3715
|
-
let index
|
|
3813
|
+
let index;
|
|
3716
3814
|
return {
|
|
3717
3815
|
get: (key) => values.get(key),
|
|
3718
3816
|
has: (key) => values.has(key),
|
|
@@ -3720,7 +3818,7 @@ const createCollectionState = (initial) => {
|
|
|
3720
3818
|
size: () => values.size,
|
|
3721
3819
|
ids: () => ids,
|
|
3722
3820
|
read: (check) => {
|
|
3723
|
-
const snapshotIndex = index;
|
|
3821
|
+
const snapshotIndex = index ??= PersistentKeyedIndex.from(values);
|
|
3724
3822
|
const snapshotIds = ids;
|
|
3725
3823
|
return Object.freeze({
|
|
3726
3824
|
get: (key) => {
|
|
@@ -3741,9 +3839,9 @@ const createCollectionState = (initial) => {
|
|
|
3741
3839
|
if (reset) {
|
|
3742
3840
|
values.clear();
|
|
3743
3841
|
for (const [key, entry] of staged) if (entry.present) values.set(key, entry.value);
|
|
3744
|
-
index = PersistentKeyedIndex.from(values);
|
|
3842
|
+
if (index) index = PersistentKeyedIndex.from(values);
|
|
3745
3843
|
} else for (const [key, entry] of staged) {
|
|
3746
|
-
index = entry.present ? index.set(key, entry.value) : index.remove(key);
|
|
3844
|
+
if (index) index = entry.present ? index.set(key, entry.value) : index.remove(key);
|
|
3747
3845
|
if (entry.present) values.set(key, entry.value);
|
|
3748
3846
|
else values.delete(key);
|
|
3749
3847
|
}
|
|
@@ -3752,17 +3850,17 @@ const createCollectionState = (initial) => {
|
|
|
3752
3850
|
release: () => {
|
|
3753
3851
|
values.clear();
|
|
3754
3852
|
ids = Object.freeze([]);
|
|
3755
|
-
index =
|
|
3853
|
+
index = void 0;
|
|
3756
3854
|
}
|
|
3757
3855
|
};
|
|
3758
3856
|
};
|
|
3759
3857
|
//#endregion
|
|
3760
3858
|
//#region core/src/projection/output/collection.ts
|
|
3761
|
-
/** Owns staged keyed intent, exact transitions and
|
|
3859
|
+
/** Owns staged keyed intent, exact transitions and current collection state. */
|
|
3762
3860
|
const createCollectionOutput = (binding) => {
|
|
3763
|
-
const
|
|
3861
|
+
const currentState = createCollectionState();
|
|
3764
3862
|
const staged = /* @__PURE__ */ new Map();
|
|
3765
|
-
let nextIds =
|
|
3863
|
+
let nextIds = currentState.ids();
|
|
3766
3864
|
let change;
|
|
3767
3865
|
let initialized = false;
|
|
3768
3866
|
let reset = false;
|
|
@@ -3770,23 +3868,26 @@ const createCollectionOutput = (binding) => {
|
|
|
3770
3868
|
let explicitOrder;
|
|
3771
3869
|
let cleared = false;
|
|
3772
3870
|
const listeners = /* @__PURE__ */ new Set();
|
|
3773
|
-
const consumers = /* @__PURE__ */ new
|
|
3774
|
-
const
|
|
3871
|
+
const consumers = /* @__PURE__ */ new Map();
|
|
3872
|
+
const notifications = createCollectionChanges();
|
|
3873
|
+
const observers = /* @__PURE__ */ new Set();
|
|
3874
|
+
let baseline;
|
|
3875
|
+
const hasNext = (key) => staged.has(key) ? staged.get(key).present : !cleared && currentState.has(key);
|
|
3775
3876
|
const getNext = (key) => {
|
|
3776
3877
|
const entry = staged.get(key);
|
|
3777
|
-
return entry ? entry.present ? entry.value : void 0 : cleared ? void 0 :
|
|
3878
|
+
return entry ? entry.present ? entry.value : void 0 : cleared ? void 0 : currentState.get(key);
|
|
3778
3879
|
};
|
|
3779
3880
|
const deriveIds = () => {
|
|
3780
3881
|
const result = [];
|
|
3781
3882
|
if (!cleared) {
|
|
3782
|
-
for (const key of
|
|
3883
|
+
for (const key of currentState.ids()) if (hasNext(key)) result.push(key);
|
|
3783
3884
|
}
|
|
3784
|
-
for (const [key, entry] of staged) if (entry.present && (cleared || !
|
|
3885
|
+
for (const [key, entry] of staged) if (entry.present && (cleared || !currentState.has(key))) result.push(key);
|
|
3785
3886
|
return result;
|
|
3786
3887
|
};
|
|
3787
3888
|
const begin = (active, initialize) => {
|
|
3788
3889
|
staged.clear();
|
|
3789
|
-
nextIds =
|
|
3890
|
+
nextIds = currentState.ids();
|
|
3790
3891
|
change = void 0;
|
|
3791
3892
|
explicitOrder = void 0;
|
|
3792
3893
|
cleared = initialize;
|
|
@@ -3794,15 +3895,15 @@ const createCollectionOutput = (binding) => {
|
|
|
3794
3895
|
const read = (next) => ({
|
|
3795
3896
|
get: (key) => {
|
|
3796
3897
|
require_transform.assertScope(active);
|
|
3797
|
-
return next ? getNext(key) :
|
|
3898
|
+
return next ? getNext(key) : currentState.get(key);
|
|
3798
3899
|
},
|
|
3799
3900
|
has: (key) => {
|
|
3800
3901
|
require_transform.assertScope(active);
|
|
3801
|
-
return next ? hasNext(key) :
|
|
3902
|
+
return next ? hasNext(key) : currentState.has(key);
|
|
3802
3903
|
},
|
|
3803
3904
|
ids: () => {
|
|
3804
3905
|
require_transform.assertScope(active);
|
|
3805
|
-
if (!next) return
|
|
3906
|
+
if (!next) return currentState.ids();
|
|
3806
3907
|
if (explicitOrder) return explicitOrder;
|
|
3807
3908
|
return Object.freeze(deriveIds());
|
|
3808
3909
|
}
|
|
@@ -3832,15 +3933,28 @@ const createCollectionOutput = (binding) => {
|
|
|
3832
3933
|
};
|
|
3833
3934
|
const seal = (nextReset, isEqual) => {
|
|
3834
3935
|
if (cleared) {
|
|
3835
|
-
for (const key of
|
|
3936
|
+
for (const key of currentState.keys()) if (!staged.has(key)) staged.set(key, { present: false });
|
|
3836
3937
|
}
|
|
3837
3938
|
require_transform.profile.projection("touchedKeys", staged.size);
|
|
3838
3939
|
const addedEntries = [];
|
|
3839
3940
|
const updatedEntries = [];
|
|
3840
3941
|
const removedEntries = [];
|
|
3841
|
-
for (const [key,
|
|
3842
|
-
|
|
3942
|
+
for (const [key, original] of staged) {
|
|
3943
|
+
let entry = original;
|
|
3944
|
+
const existed = currentState.has(key);
|
|
3843
3945
|
if (entry.present) {
|
|
3946
|
+
if (baseline?.has(key) && (!existed || !Object.is(currentState.get(key), baseline.get(key)))) {
|
|
3947
|
+
const before = baseline.get(key);
|
|
3948
|
+
const equivalent = isEqual(before, entry.value);
|
|
3949
|
+
require_transform.assertSynchronous(equivalent);
|
|
3950
|
+
if (equivalent) {
|
|
3951
|
+
entry = {
|
|
3952
|
+
present: true,
|
|
3953
|
+
value: before
|
|
3954
|
+
};
|
|
3955
|
+
staged.set(key, entry);
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3844
3958
|
if (!existed) {
|
|
3845
3959
|
addedEntries.push({
|
|
3846
3960
|
key,
|
|
@@ -3848,7 +3962,7 @@ const createCollectionOutput = (binding) => {
|
|
|
3848
3962
|
});
|
|
3849
3963
|
continue;
|
|
3850
3964
|
}
|
|
3851
|
-
const before =
|
|
3965
|
+
const before = currentState.get(key);
|
|
3852
3966
|
const equal = isEqual(before, entry.value);
|
|
3853
3967
|
require_transform.assertSynchronous(equal);
|
|
3854
3968
|
if (!equal) updatedEntries.push({
|
|
@@ -3865,13 +3979,13 @@ const createCollectionOutput = (binding) => {
|
|
|
3865
3979
|
}
|
|
3866
3980
|
if (existed) removedEntries.push({
|
|
3867
3981
|
key,
|
|
3868
|
-
before:
|
|
3982
|
+
before: currentState.get(key)
|
|
3869
3983
|
});
|
|
3870
3984
|
else staged.delete(key);
|
|
3871
3985
|
}
|
|
3872
|
-
const ids =
|
|
3986
|
+
const ids = currentState.ids();
|
|
3873
3987
|
if (explicitOrder) {
|
|
3874
|
-
const expectedLength =
|
|
3988
|
+
const expectedLength = currentState.size() + addedEntries.length - removedEntries.length;
|
|
3875
3989
|
const seen = /* @__PURE__ */ new Set();
|
|
3876
3990
|
for (const key of explicitOrder) {
|
|
3877
3991
|
if (seen.has(key) || !hasNext(key)) throw new TypeError("Projection order must contain every key exactly once.");
|
|
@@ -3880,7 +3994,7 @@ const createCollectionOutput = (binding) => {
|
|
|
3880
3994
|
if (seen.size !== expectedLength) throw new TypeError("Projection order must contain every key exactly once.");
|
|
3881
3995
|
nextIds = require_transform.sameArray(ids, explicitOrder) ? ids : explicitOrder;
|
|
3882
3996
|
} else if (addedEntries.length || removedEntries.length) {
|
|
3883
|
-
const order = new Array(
|
|
3997
|
+
const order = new Array(currentState.size() + addedEntries.length - removedEntries.length);
|
|
3884
3998
|
let index = 0;
|
|
3885
3999
|
for (const key of ids) if (hasNext(key)) order[index++] = key;
|
|
3886
4000
|
for (const entry of addedEntries) order[index++] = entry.key;
|
|
@@ -3897,7 +4011,7 @@ const createCollectionOutput = (binding) => {
|
|
|
3897
4011
|
reset = nextReset;
|
|
3898
4012
|
return change !== void 0;
|
|
3899
4013
|
};
|
|
3900
|
-
const context = (active, cause) => Object.freeze({
|
|
4014
|
+
const context = (active, cause, consumer) => Object.freeze({
|
|
3901
4015
|
kind: "collection",
|
|
3902
4016
|
read: {
|
|
3903
4017
|
get: (key) => {
|
|
@@ -3913,9 +4027,9 @@ const createCollectionOutput = (binding) => {
|
|
|
3913
4027
|
return nextIds;
|
|
3914
4028
|
}
|
|
3915
4029
|
},
|
|
3916
|
-
change,
|
|
4030
|
+
change: consumer ? consumers.get(consumer)?.current() : change,
|
|
3917
4031
|
revision,
|
|
3918
|
-
reset,
|
|
4032
|
+
reset: consumer ? consumers.get(consumer)?.reset() ?? false : reset,
|
|
3919
4033
|
cause
|
|
3920
4034
|
});
|
|
3921
4035
|
return {
|
|
@@ -3925,35 +4039,59 @@ const createCollectionOutput = (binding) => {
|
|
|
3925
4039
|
},
|
|
3926
4040
|
begin,
|
|
3927
4041
|
seal,
|
|
3928
|
-
context: (active) => context(active, binding.cause()),
|
|
3929
|
-
|
|
4042
|
+
context: (active, consumer) => context(active, binding.cause(), consumer),
|
|
4043
|
+
acknowledge: (consumer) => consumers.get(consumer)?.clear(),
|
|
4044
|
+
pending: (consumer) => consumers.get(consumer)?.current() !== void 0,
|
|
4045
|
+
baseline: () => baseline ?? currentState.read(binding.check),
|
|
4046
|
+
current: () => currentState.read(binding.check),
|
|
3930
4047
|
revision: () => revision,
|
|
3931
|
-
reset: () => reset,
|
|
4048
|
+
reset: (consumer) => consumer ? consumers.get(consumer)?.reset() ?? false : reset,
|
|
3932
4049
|
publish: () => {
|
|
3933
|
-
if (change)
|
|
3934
|
-
|
|
4050
|
+
if (change) {
|
|
4051
|
+
if (initialized) {
|
|
4052
|
+
baseline ??= currentState.read(() => void 0);
|
|
4053
|
+
notifications.add(change, currentState.ids(), nextIds);
|
|
4054
|
+
for (const pending of consumers.values()) pending.add(change, currentState.ids(), nextIds);
|
|
4055
|
+
revision++;
|
|
4056
|
+
}
|
|
4057
|
+
currentState.install(staged, nextIds, change.kind === "reset");
|
|
4058
|
+
}
|
|
3935
4059
|
initialized = true;
|
|
3936
4060
|
},
|
|
3937
|
-
emit: (call) => {
|
|
3938
|
-
|
|
4061
|
+
emit: (call, force) => {
|
|
4062
|
+
const net = notifications.current();
|
|
4063
|
+
for (const listener of [...observers]) call(listener, net);
|
|
4064
|
+
if (net || force) for (const listener of [...listeners]) call(listener, net);
|
|
4065
|
+
},
|
|
4066
|
+
finish: () => {
|
|
4067
|
+
baseline = void 0;
|
|
4068
|
+
notifications.clear();
|
|
4069
|
+
},
|
|
4070
|
+
observe: (listener) => {
|
|
4071
|
+
binding.check();
|
|
4072
|
+
observers.add(listener);
|
|
4073
|
+
return () => observers.delete(listener);
|
|
3939
4074
|
},
|
|
3940
4075
|
hasConsumers: () => consumers.size > 0,
|
|
3941
|
-
forEachConsumer: (run) => consumers.forEach(run),
|
|
3942
|
-
attachConsumer: (consumer) => consumers.
|
|
4076
|
+
forEachConsumer: (run) => consumers.forEach((_pending, consumer) => run(consumer)),
|
|
4077
|
+
attachConsumer: (consumer) => consumers.set(consumer, createCollectionChanges()),
|
|
3943
4078
|
detachConsumer: (consumer) => consumers.delete(consumer),
|
|
3944
4079
|
clear: () => {
|
|
3945
4080
|
staged.clear();
|
|
3946
|
-
nextIds =
|
|
4081
|
+
nextIds = currentState.ids();
|
|
3947
4082
|
change = void 0;
|
|
3948
4083
|
reset = false;
|
|
3949
4084
|
explicitOrder = void 0;
|
|
3950
4085
|
cleared = false;
|
|
3951
4086
|
},
|
|
3952
4087
|
release: () => {
|
|
3953
|
-
|
|
4088
|
+
currentState.release();
|
|
3954
4089
|
staged.clear();
|
|
3955
4090
|
listeners.clear();
|
|
3956
4091
|
consumers.clear();
|
|
4092
|
+
observers.clear();
|
|
4093
|
+
baseline = void 0;
|
|
4094
|
+
notifications.clear();
|
|
3957
4095
|
nextIds = Object.freeze([]);
|
|
3958
4096
|
change = void 0;
|
|
3959
4097
|
initialized = false;
|
|
@@ -3972,7 +4110,7 @@ const createCollectionOutput = (binding) => {
|
|
|
3972
4110
|
//#endregion
|
|
3973
4111
|
//#region core/src/projection/output/value.ts
|
|
3974
4112
|
const unset = Symbol("projection-value-unset");
|
|
3975
|
-
/** Owns staged and
|
|
4113
|
+
/** Owns staged and current state for one scalar Projection output. */
|
|
3976
4114
|
const createValueOutput = (binding) => {
|
|
3977
4115
|
let value;
|
|
3978
4116
|
let staged = unset;
|
|
@@ -3982,7 +4120,10 @@ const createValueOutput = (binding) => {
|
|
|
3982
4120
|
let changed = false;
|
|
3983
4121
|
let reset = false;
|
|
3984
4122
|
const listeners = /* @__PURE__ */ new Set();
|
|
3985
|
-
const consumers = /* @__PURE__ */ new
|
|
4123
|
+
const consumers = /* @__PURE__ */ new Map();
|
|
4124
|
+
const observers = /* @__PURE__ */ new Set();
|
|
4125
|
+
let baseline = unset;
|
|
4126
|
+
let resetRevision = -1;
|
|
3986
4127
|
const begin = (active, initialize) => {
|
|
3987
4128
|
staged = unset;
|
|
3988
4129
|
next = value;
|
|
@@ -4009,7 +4150,12 @@ const createValueOutput = (binding) => {
|
|
|
4009
4150
|
next = value;
|
|
4010
4151
|
return false;
|
|
4011
4152
|
}
|
|
4012
|
-
|
|
4153
|
+
let candidate = staged;
|
|
4154
|
+
if (baseline !== unset && !Object.is(value, baseline)) {
|
|
4155
|
+
const equivalent = isEqual(baseline, candidate);
|
|
4156
|
+
require_transform.assertSynchronous(equivalent);
|
|
4157
|
+
if (equivalent) candidate = baseline;
|
|
4158
|
+
}
|
|
4013
4159
|
const equal = initialized ? isEqual(value, candidate) : false;
|
|
4014
4160
|
require_transform.assertSynchronous(equal);
|
|
4015
4161
|
changed = !equal;
|
|
@@ -4024,13 +4170,13 @@ const createValueOutput = (binding) => {
|
|
|
4024
4170
|
},
|
|
4025
4171
|
begin,
|
|
4026
4172
|
seal,
|
|
4027
|
-
context: (active) => {
|
|
4173
|
+
context: (active, consumer) => {
|
|
4028
4174
|
require_transform.assertScope(active);
|
|
4029
4175
|
return Object.freeze({
|
|
4030
4176
|
kind: "value",
|
|
4031
4177
|
value: next,
|
|
4032
4178
|
revision,
|
|
4033
|
-
reset,
|
|
4179
|
+
reset: consumer ? (consumers.get(consumer)?.revision ?? -1) < resetRevision : reset,
|
|
4034
4180
|
cause: binding.cause()
|
|
4035
4181
|
});
|
|
4036
4182
|
},
|
|
@@ -4039,19 +4185,48 @@ const createValueOutput = (binding) => {
|
|
|
4039
4185
|
return value;
|
|
4040
4186
|
},
|
|
4041
4187
|
revision: () => revision,
|
|
4042
|
-
reset: () => reset,
|
|
4043
|
-
|
|
4044
|
-
if (
|
|
4188
|
+
reset: (consumer) => consumer ? (consumers.get(consumer)?.revision ?? -1) < resetRevision : reset,
|
|
4189
|
+
acknowledge: (consumer) => {
|
|
4190
|
+
if (consumers.has(consumer)) consumers.set(consumer, {
|
|
4191
|
+
revision,
|
|
4192
|
+
value
|
|
4193
|
+
});
|
|
4194
|
+
},
|
|
4195
|
+
pending: (consumer) => {
|
|
4196
|
+
const previous = consumers.get(consumer);
|
|
4197
|
+
return !previous || previous.revision < resetRevision || !Object.is(previous.value, value);
|
|
4198
|
+
},
|
|
4199
|
+
baseline: () => baseline === unset ? value : baseline,
|
|
4200
|
+
publish: (forceReset) => {
|
|
4201
|
+
if (initialized && (changed || forceReset)) {
|
|
4202
|
+
if (baseline === unset) baseline = value;
|
|
4203
|
+
revision++;
|
|
4204
|
+
if (reset) resetRevision = revision;
|
|
4205
|
+
}
|
|
4045
4206
|
if (changed) value = next;
|
|
4046
4207
|
initialized = true;
|
|
4047
4208
|
},
|
|
4048
|
-
emit: (call) => {
|
|
4049
|
-
|
|
4050
|
-
|
|
4209
|
+
emit: (call, force) => {
|
|
4210
|
+
for (const listener of [...observers]) call(listener, void 0);
|
|
4211
|
+
if (force || baseline !== unset && !Object.is(baseline, value)) {
|
|
4212
|
+
require_transform.profile.materialized.notification();
|
|
4213
|
+
for (const listener of [...listeners]) call(listener, void 0);
|
|
4214
|
+
}
|
|
4215
|
+
},
|
|
4216
|
+
finish: () => {
|
|
4217
|
+
baseline = unset;
|
|
4218
|
+
},
|
|
4219
|
+
observe: (listener) => {
|
|
4220
|
+
binding.check();
|
|
4221
|
+
observers.add(listener);
|
|
4222
|
+
return () => observers.delete(listener);
|
|
4051
4223
|
},
|
|
4052
4224
|
hasConsumers: () => consumers.size > 0,
|
|
4053
|
-
forEachConsumer: (run) => consumers.forEach(run),
|
|
4054
|
-
attachConsumer: (consumer) => consumers.
|
|
4225
|
+
forEachConsumer: (run) => consumers.forEach((_revision, consumer) => run(consumer)),
|
|
4226
|
+
attachConsumer: (consumer) => consumers.set(consumer, {
|
|
4227
|
+
revision,
|
|
4228
|
+
value
|
|
4229
|
+
}),
|
|
4055
4230
|
detachConsumer: (consumer) => consumers.delete(consumer),
|
|
4056
4231
|
clear: () => {
|
|
4057
4232
|
staged = unset;
|
|
@@ -4062,6 +4237,8 @@ const createValueOutput = (binding) => {
|
|
|
4062
4237
|
release: () => {
|
|
4063
4238
|
listeners.clear();
|
|
4064
4239
|
consumers.clear();
|
|
4240
|
+
observers.clear();
|
|
4241
|
+
baseline = unset;
|
|
4065
4242
|
staged = unset;
|
|
4066
4243
|
value = next = void 0;
|
|
4067
4244
|
initialized = false;
|
|
@@ -4132,7 +4309,7 @@ const createProcessor = (scheduler, definition, dependencies) => {
|
|
|
4132
4309
|
let active = true;
|
|
4133
4310
|
try {
|
|
4134
4311
|
const scopeActive = () => active;
|
|
4135
|
-
const sources = Object.freeze(dependencies.map((output) => output.context(scopeActive)));
|
|
4312
|
+
const sources = Object.freeze(dependencies.map((output) => output.context(scopeActive, processor)));
|
|
4136
4313
|
const outputs = begin(scopeActive, reset);
|
|
4137
4314
|
if (recreate && instance) {
|
|
4138
4315
|
instance.release?.();
|
|
@@ -4146,16 +4323,17 @@ const createProcessor = (scheduler, definition, dependencies) => {
|
|
|
4146
4323
|
sources,
|
|
4147
4324
|
outputs
|
|
4148
4325
|
}));
|
|
4149
|
-
|
|
4326
|
+
const changed = seal(reset);
|
|
4327
|
+
dependencies.forEach((output) => output.acknowledge(processor));
|
|
4328
|
+
return changed;
|
|
4150
4329
|
} finally {
|
|
4151
4330
|
active = false;
|
|
4152
4331
|
}
|
|
4153
4332
|
};
|
|
4154
|
-
const
|
|
4333
|
+
const id = scheduler.nextId();
|
|
4155
4334
|
processor = {
|
|
4156
4335
|
kind: "processor",
|
|
4157
|
-
|
|
4158
|
-
name: definition.name ? `${definition.name} (${order})` : `projection-${order}`,
|
|
4336
|
+
name: definition.name ? `${definition.name} (${id})` : `projection-${id}`,
|
|
4159
4337
|
dependencies: Object.freeze([...dependencies]),
|
|
4160
4338
|
outputs: Object.freeze(bound.map((entry) => entry.state)),
|
|
4161
4339
|
fault: void 0,
|
|
@@ -4282,7 +4460,9 @@ const createSelectorReadable = (source, selector, equality = Object.is) => {
|
|
|
4282
4460
|
let initialized = false;
|
|
4283
4461
|
let value;
|
|
4284
4462
|
let selectedRevision = 0;
|
|
4463
|
+
let notified;
|
|
4285
4464
|
let sourceRevision = -1;
|
|
4465
|
+
let notificationRevision = -1;
|
|
4286
4466
|
let selection = Object.freeze({
|
|
4287
4467
|
keys: /* @__PURE__ */ new Set(),
|
|
4288
4468
|
all: true,
|
|
@@ -4318,8 +4498,9 @@ const createSelectorReadable = (source, selector, equality = Object.is) => {
|
|
|
4318
4498
|
});
|
|
4319
4499
|
const changed = !initialized || !equality(value, next);
|
|
4320
4500
|
if (changed) {
|
|
4501
|
+
const candidate = unsubscribeSource && equality(notified, next) ? notified : next;
|
|
4321
4502
|
if (initialized) selectedRevision++;
|
|
4322
|
-
value =
|
|
4503
|
+
value = candidate;
|
|
4323
4504
|
}
|
|
4324
4505
|
selection = nextSelection;
|
|
4325
4506
|
initialized = true;
|
|
@@ -4329,31 +4510,44 @@ const createSelectorReadable = (source, selector, equality = Object.is) => {
|
|
|
4329
4510
|
};
|
|
4330
4511
|
const ensureCurrent = () => {
|
|
4331
4512
|
const revision = source.revision();
|
|
4332
|
-
if (!initialized
|
|
4333
|
-
|
|
4334
|
-
};
|
|
4335
|
-
const onProjectionChange = (incoming) => {
|
|
4336
|
-
let change = incoming;
|
|
4337
|
-
if (!change && previousCollection) {
|
|
4513
|
+
if (!initialized) evaluate();
|
|
4514
|
+
else if (sourceRevision !== revision) {
|
|
4338
4515
|
const current = source.current();
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
if (!
|
|
4343
|
-
|
|
4344
|
-
|
|
4516
|
+
let affected = true;
|
|
4517
|
+
if (previousCollection && isMapLike(current) && !selection.all) {
|
|
4518
|
+
affected = selection.structure && !require_transform.iterableMatchesArray(current.keys(), [...previousCollection.keys()]);
|
|
4519
|
+
if (!affected) {
|
|
4520
|
+
for (const key of selection.keys) if (previousCollection.has(key) !== current.has(key) || !Object.is(previousCollection.get(key), current.get(key))) {
|
|
4521
|
+
affected = true;
|
|
4522
|
+
break;
|
|
4523
|
+
}
|
|
4345
4524
|
}
|
|
4346
|
-
}
|
|
4525
|
+
}
|
|
4526
|
+
if (affected) evaluate();
|
|
4527
|
+
else {
|
|
4528
|
+
sourceRevision = revision;
|
|
4529
|
+
updateCollectionSnapshot(current);
|
|
4530
|
+
}
|
|
4347
4531
|
}
|
|
4348
|
-
|
|
4532
|
+
return value;
|
|
4533
|
+
};
|
|
4534
|
+
const onProjectionChange = (incoming) => {
|
|
4535
|
+
if (sourceRevision === notificationRevision && sourceRevision !== source.revision() && incoming && !selectionAffects(selection, incoming)) {
|
|
4349
4536
|
sourceRevision = source.revision();
|
|
4350
4537
|
updateCollectionSnapshot();
|
|
4351
|
-
|
|
4538
|
+
} else ensureCurrent();
|
|
4539
|
+
notificationRevision = sourceRevision;
|
|
4540
|
+
if (!equality(notified, value)) {
|
|
4541
|
+
notified = value;
|
|
4542
|
+
notifyProjectionListeners(listeners, "Projection selector listeners failed.");
|
|
4352
4543
|
}
|
|
4353
|
-
if (evaluate()) notifyProjectionListeners(listeners, "Projection selector listeners failed.");
|
|
4354
4544
|
};
|
|
4355
4545
|
const installSource = () => {
|
|
4356
|
-
if (!unsubscribeSource)
|
|
4546
|
+
if (!unsubscribeSource) {
|
|
4547
|
+
notified = value;
|
|
4548
|
+
notificationRevision = sourceRevision;
|
|
4549
|
+
unsubscribeSource = source.observe(onProjectionChange);
|
|
4550
|
+
}
|
|
4357
4551
|
};
|
|
4358
4552
|
return Object.freeze({
|
|
4359
4553
|
current: ensureCurrent,
|
|
@@ -4735,13 +4929,12 @@ const createValueBoundary = (scheduler, name, initial, equality, prepare, clearS
|
|
|
4735
4929
|
active = false;
|
|
4736
4930
|
}
|
|
4737
4931
|
},
|
|
4738
|
-
publish: state.publish,
|
|
4932
|
+
publish: () => state.publish(pendingReset),
|
|
4739
4933
|
clear: () => {
|
|
4740
4934
|
const failed = boundary.fault !== void 0;
|
|
4741
4935
|
state.clear();
|
|
4742
4936
|
pendingReset = false;
|
|
4743
4937
|
pendingCause = void 0;
|
|
4744
|
-
contextCause = void 0;
|
|
4745
4938
|
recovering = false;
|
|
4746
4939
|
clearSource(failed);
|
|
4747
4940
|
},
|
|
@@ -4797,6 +4990,7 @@ const createValueBoundary = (scheduler, name, initial, equality, prepare, clearS
|
|
|
4797
4990
|
return {
|
|
4798
4991
|
producer: boundary,
|
|
4799
4992
|
output,
|
|
4993
|
+
baseline: state.baseline,
|
|
4800
4994
|
mark,
|
|
4801
4995
|
fail,
|
|
4802
4996
|
detach: (next) => {
|
|
@@ -4816,7 +5010,7 @@ const stageCollectionRead = (state, read, active, options) => {
|
|
|
4816
5010
|
}
|
|
4817
5011
|
evaluation.output.order(ids);
|
|
4818
5012
|
} else {
|
|
4819
|
-
const previous =
|
|
5013
|
+
const previous = evaluation.previous;
|
|
4820
5014
|
let currentIds;
|
|
4821
5015
|
const ids = () => currentIds ??= read.ids();
|
|
4822
5016
|
if (options.candidates) for (const key of options.candidates) if (read.has(key)) {
|
|
@@ -4897,7 +5091,6 @@ const createCollectionBoundary = (scheduler, name, readLatest, equality, clearSo
|
|
|
4897
5091
|
state.clear();
|
|
4898
5092
|
pendingReset = false;
|
|
4899
5093
|
pendingCause = void 0;
|
|
4900
|
-
contextCause = void 0;
|
|
4901
5094
|
recovering = false;
|
|
4902
5095
|
fullScan = false;
|
|
4903
5096
|
orderMayChange = false;
|
|
@@ -4950,7 +5143,11 @@ const createCollectionBoundary = (scheduler, name, readLatest, equality, clearSo
|
|
|
4950
5143
|
fullScan ||= metadata.fullScan ?? false;
|
|
4951
5144
|
orderMayChange ||= metadata.orderMayChange ?? false;
|
|
4952
5145
|
if (metadata.candidates) for (const key of metadata.candidates) candidates.add(key);
|
|
4953
|
-
if (boundary.fault)
|
|
5146
|
+
if (boundary.fault) {
|
|
5147
|
+
recovering = true;
|
|
5148
|
+
fullScan = true;
|
|
5149
|
+
orderMayChange = true;
|
|
5150
|
+
}
|
|
4954
5151
|
scheduler.capture(boundary);
|
|
4955
5152
|
};
|
|
4956
5153
|
const fail = (cause) => {
|
|
@@ -4961,6 +5158,7 @@ const createCollectionBoundary = (scheduler, name, readLatest, equality, clearSo
|
|
|
4961
5158
|
return {
|
|
4962
5159
|
producer: boundary,
|
|
4963
5160
|
output,
|
|
5161
|
+
baseline: state.baseline,
|
|
4964
5162
|
mark,
|
|
4965
5163
|
fail,
|
|
4966
5164
|
detach: (next) => {
|
|
@@ -5510,13 +5708,12 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5510
5708
|
...boundary,
|
|
5511
5709
|
input: {
|
|
5512
5710
|
kind: "value",
|
|
5513
|
-
read: () => latest,
|
|
5514
5711
|
set(value) {
|
|
5515
5712
|
const next = scheduler.acceptInput(() => {
|
|
5516
5713
|
if (equal(latest, value)) return latest;
|
|
5517
5714
|
if (source.equality === Object.is) return value;
|
|
5518
|
-
const
|
|
5519
|
-
return !Object.is(latest,
|
|
5715
|
+
const baseline = boundary.baseline();
|
|
5716
|
+
return !Object.is(latest, baseline) && equal(baseline, value) ? baseline : value;
|
|
5520
5717
|
});
|
|
5521
5718
|
if (Object.is(latest, next)) return;
|
|
5522
5719
|
latest = next;
|
|
@@ -5527,7 +5724,6 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5527
5724
|
};
|
|
5528
5725
|
}
|
|
5529
5726
|
const values = createCollectionState(source.initial);
|
|
5530
|
-
let view;
|
|
5531
5727
|
const latest = {
|
|
5532
5728
|
get: values.get,
|
|
5533
5729
|
has: values.has,
|
|
@@ -5536,17 +5732,11 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5536
5732
|
const boundary = createCollectionBoundary(scheduler, "projection collection input", () => latest, Object.is, () => void 0);
|
|
5537
5733
|
boundary.detach(() => {
|
|
5538
5734
|
values.release();
|
|
5539
|
-
view = void 0;
|
|
5540
5735
|
});
|
|
5541
|
-
const check = () => {
|
|
5542
|
-
scheduler.assertActive();
|
|
5543
|
-
if (boundary.producer.disposed) throw new require_transform.ProjectionDisposedError();
|
|
5544
|
-
};
|
|
5545
5736
|
return {
|
|
5546
5737
|
...boundary,
|
|
5547
5738
|
input: {
|
|
5548
5739
|
kind: "collection",
|
|
5549
|
-
read: () => view ??= require_transform.collectionView(values.read(check)),
|
|
5550
5740
|
update(run) {
|
|
5551
5741
|
const accepted = scheduler.acceptInput(() => {
|
|
5552
5742
|
const staged = /* @__PURE__ */ new Map();
|
|
@@ -5593,7 +5783,7 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5593
5783
|
} finally {
|
|
5594
5784
|
active = false;
|
|
5595
5785
|
}
|
|
5596
|
-
const
|
|
5786
|
+
const baseline = source.equality === Object.is ? void 0 : boundary.baseline();
|
|
5597
5787
|
for (const [key, entry] of staged) {
|
|
5598
5788
|
const existed = values.has(key);
|
|
5599
5789
|
if (!entry.present) {
|
|
@@ -5603,8 +5793,8 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5603
5793
|
const previous = values.get(key);
|
|
5604
5794
|
let next = entry.value;
|
|
5605
5795
|
if (existed && equal(previous, next)) next = previous;
|
|
5606
|
-
else if (
|
|
5607
|
-
const before =
|
|
5796
|
+
else if (baseline?.has(key)) {
|
|
5797
|
+
const before = baseline.get(key);
|
|
5608
5798
|
if ((!existed || !Object.is(previous, before)) && equal(before, next)) next = before;
|
|
5609
5799
|
}
|
|
5610
5800
|
if (existed && Object.is(previous, next)) staged.delete(key);
|
|
@@ -5629,7 +5819,6 @@ const materializeInputSource = (scheduler, definition) => {
|
|
|
5629
5819
|
});
|
|
5630
5820
|
if (!accepted.staged.size && !accepted.structural) return;
|
|
5631
5821
|
values.install(accepted.staged, accepted.order, false);
|
|
5632
|
-
view = void 0;
|
|
5633
5822
|
boundary.mark({
|
|
5634
5823
|
candidates: accepted.staged.keys(),
|
|
5635
5824
|
orderMayChange: accepted.structural
|
|
@@ -5682,6 +5871,11 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5682
5871
|
const waiting = /* @__PURE__ */ new Map();
|
|
5683
5872
|
let keysValue = Object.freeze([...source.current().keys()]);
|
|
5684
5873
|
let keysRevision = 0;
|
|
5874
|
+
let notifiedKeys = keysValue;
|
|
5875
|
+
let settledRevision = source.revision();
|
|
5876
|
+
let keysSourceRevision = settledRevision;
|
|
5877
|
+
const pendingKeys = /* @__PURE__ */ new Set();
|
|
5878
|
+
const changedStates = /* @__PURE__ */ new Set();
|
|
5685
5879
|
const keyListeners = /* @__PURE__ */ new Set();
|
|
5686
5880
|
const check = () => {
|
|
5687
5881
|
if (disposed) throw new require_transform.ProjectionDisposedError();
|
|
@@ -5717,7 +5911,7 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5717
5911
|
}
|
|
5718
5912
|
state.value = value;
|
|
5719
5913
|
state.revision++;
|
|
5720
|
-
|
|
5914
|
+
changedStates.add(state);
|
|
5721
5915
|
};
|
|
5722
5916
|
const attachActive = (state, value) => {
|
|
5723
5917
|
if (state.ended) return;
|
|
@@ -5760,10 +5954,12 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5760
5954
|
if (extra) for (const state of extra) publishState(state, value);
|
|
5761
5955
|
};
|
|
5762
5956
|
const updateKeys = (current) => {
|
|
5957
|
+
const revision = source.revision();
|
|
5958
|
+
if (keysSourceRevision === revision) return;
|
|
5959
|
+
keysSourceRevision = revision;
|
|
5763
5960
|
if (require_transform.iterableMatchesArray(current.keys(), keysValue)) return;
|
|
5764
|
-
keysValue = Object.freeze([...current.keys()]);
|
|
5961
|
+
keysValue = require_transform.iterableMatchesArray(current.keys(), notifiedKeys) ? notifiedKeys : Object.freeze([...current.keys()]);
|
|
5765
5962
|
keysRevision++;
|
|
5766
|
-
notify(keyListeners);
|
|
5767
5963
|
};
|
|
5768
5964
|
const createItem = (key, initial) => {
|
|
5769
5965
|
const state = {
|
|
@@ -5772,12 +5968,15 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5772
5968
|
tracked: initial !== void 0,
|
|
5773
5969
|
ended: false,
|
|
5774
5970
|
value: initial?.value,
|
|
5971
|
+
notified: initial?.value,
|
|
5775
5972
|
revision: 0
|
|
5776
5973
|
};
|
|
5777
5974
|
const ensureObserved = () => {
|
|
5778
|
-
if (state.ended
|
|
5975
|
+
if (state.ended) return;
|
|
5779
5976
|
const current = source.current();
|
|
5780
|
-
if (
|
|
5977
|
+
if (source.revision() !== settledRevision) pendingKeys.add(key);
|
|
5978
|
+
if (!state.tracked && current.has(key)) attachActive(state, current.get(key));
|
|
5979
|
+
else if (state.tracked) publishState(state, current.get(key));
|
|
5781
5980
|
};
|
|
5782
5981
|
state.readable = Object.freeze({
|
|
5783
5982
|
current: () => {
|
|
@@ -5812,25 +6011,45 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5812
6011
|
const onChange = (change) => {
|
|
5813
6012
|
check();
|
|
5814
6013
|
const current = source.current();
|
|
5815
|
-
if (
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
6014
|
+
if (change?.kind === "reset") reconcile(current);
|
|
6015
|
+
else {
|
|
6016
|
+
if (change) {
|
|
6017
|
+
for (const entry of change.removed) terminateKey(entry.key);
|
|
6018
|
+
for (const entry of change.added) activateWaiting(entry.key, entry.after);
|
|
6019
|
+
for (const entry of change.updated) updateKey(entry.key, entry.after);
|
|
6020
|
+
if (change.added.length || change.removed.length || change.order) updateKeys(current);
|
|
6021
|
+
}
|
|
6022
|
+
for (const key of pendingKeys) if (!current.has(key)) terminateKey(key);
|
|
6023
|
+
else {
|
|
6024
|
+
updateKey(key, current.get(key));
|
|
6025
|
+
activateWaiting(key, current.get(key));
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
pendingKeys.clear();
|
|
6029
|
+
settledRevision = source.revision();
|
|
6030
|
+
for (const state of changedStates) if (!Object.is(state.notified, state.value)) {
|
|
6031
|
+
state.notified = state.value;
|
|
6032
|
+
notify(state.listeners);
|
|
6033
|
+
}
|
|
6034
|
+
changedStates.clear();
|
|
6035
|
+
if (keysValue !== notifiedKeys) updateKeys(current);
|
|
6036
|
+
else keysSourceRevision = settledRevision;
|
|
6037
|
+
if (keysValue !== notifiedKeys) {
|
|
6038
|
+
notifiedKeys = keysValue;
|
|
6039
|
+
notify(keyListeners);
|
|
5819
6040
|
}
|
|
5820
|
-
for (const entry of change.removed) terminateKey(entry.key);
|
|
5821
|
-
for (const entry of change.added) activateWaiting(entry.key, entry.after);
|
|
5822
|
-
for (const entry of change.updated) updateKey(entry.key, entry.after);
|
|
5823
|
-
if (change.added.length || change.removed.length || change.order) updateKeys(current);
|
|
5824
6041
|
flushNotifications();
|
|
5825
6042
|
};
|
|
5826
|
-
const stop = source.
|
|
6043
|
+
const stop = source.observe(onChange);
|
|
5827
6044
|
const keys = Object.freeze({
|
|
5828
6045
|
current: () => {
|
|
5829
6046
|
check();
|
|
6047
|
+
updateKeys(source.current());
|
|
5830
6048
|
return keysValue;
|
|
5831
6049
|
},
|
|
5832
6050
|
revision: () => {
|
|
5833
6051
|
check();
|
|
6052
|
+
updateKeys(source.current());
|
|
5834
6053
|
return keysRevision;
|
|
5835
6054
|
},
|
|
5836
6055
|
subscribe: (listener) => {
|
|
@@ -5844,11 +6063,12 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5844
6063
|
keys,
|
|
5845
6064
|
get: (key) => {
|
|
5846
6065
|
check();
|
|
6066
|
+
const current = source.current();
|
|
6067
|
+
if (source.revision() !== settledRevision) pendingKeys.add(key);
|
|
5847
6068
|
const canonical = active.get(key);
|
|
5848
6069
|
if (canonical) return canonical.readable;
|
|
5849
6070
|
const pending = waiting.get(key)?.values().next().value;
|
|
5850
6071
|
if (pending) return pending.readable;
|
|
5851
|
-
const current = source.current();
|
|
5852
6072
|
if (current.has(key)) {
|
|
5853
6073
|
const state = createItem(key, {
|
|
5854
6074
|
present: true,
|
|
@@ -5874,6 +6094,8 @@ const createProjectionItems = (source, checkOwner) => {
|
|
|
5874
6094
|
followers.clear();
|
|
5875
6095
|
waiting.clear();
|
|
5876
6096
|
notifications.length = 0;
|
|
6097
|
+
pendingKeys.clear();
|
|
6098
|
+
changedStates.clear();
|
|
5877
6099
|
}
|
|
5878
6100
|
};
|
|
5879
6101
|
};
|
|
@@ -5934,6 +6156,7 @@ const createProjectionRuntime = (options) => {
|
|
|
5934
6156
|
} else {
|
|
5935
6157
|
if (definition.owner === void 0 && definition.dependencies.some((dependency) => require_transform.producerOf(dependency).owner !== void 0)) throw new TypeError("A root projection cannot depend on a scoped projection.");
|
|
5936
6158
|
const dependencies = definition.dependencies.map((dependency) => resolveOutput(dependency, requester));
|
|
6159
|
+
dependencies.forEach((output) => scheduler.ensureCurrent(output));
|
|
5937
6160
|
const processor = createProcessor(scheduler, definition, Object.freeze(dependencies));
|
|
5938
6161
|
result = Object.freeze({
|
|
5939
6162
|
record: processor,
|
|
@@ -5957,6 +6180,7 @@ const createProjectionRuntime = (options) => {
|
|
|
5957
6180
|
if (output.owner.fault) throw output.owner.fault;
|
|
5958
6181
|
};
|
|
5959
6182
|
const publicCurrent = (output) => {
|
|
6183
|
+
scheduler.ensureCurrent(output);
|
|
5960
6184
|
assertOutput(output);
|
|
5961
6185
|
const current = output.current();
|
|
5962
6186
|
const revision = output.revision();
|
|
@@ -5988,10 +6212,12 @@ const createProjectionRuntime = (options) => {
|
|
|
5988
6212
|
kind: output.kind,
|
|
5989
6213
|
current: () => readProjection(projection, requester),
|
|
5990
6214
|
revision: () => {
|
|
6215
|
+
scheduler.ensureCurrent(output);
|
|
5991
6216
|
assertOutput(output);
|
|
5992
6217
|
return output.revision();
|
|
5993
6218
|
},
|
|
5994
|
-
subscribe: output.subscribe
|
|
6219
|
+
subscribe: output.subscribe,
|
|
6220
|
+
observe: output.observe
|
|
5995
6221
|
});
|
|
5996
6222
|
};
|
|
5997
6223
|
const projectionItems = (projection, requester) => {
|
|
@@ -6002,6 +6228,7 @@ const createProjectionRuntime = (options) => {
|
|
|
6002
6228
|
if (existing) return existing.items;
|
|
6003
6229
|
const controller = createProjectionItems(readableSource(projection, requester), () => {
|
|
6004
6230
|
if (requester && !requester.active) throw new require_transform.ProjectionDisposedError();
|
|
6231
|
+
scheduler.ensureCurrent(output);
|
|
6005
6232
|
assertOutput(output);
|
|
6006
6233
|
});
|
|
6007
6234
|
registry.set(output, controller);
|
|
@@ -6036,18 +6263,7 @@ const createProjectionRuntime = (options) => {
|
|
|
6036
6263
|
function update(target, valueOrRun) {
|
|
6037
6264
|
updateInput(target, valueOrRun);
|
|
6038
6265
|
}
|
|
6039
|
-
const batch = (run, options
|
|
6040
|
-
let active = true;
|
|
6041
|
-
const read = (target) => {
|
|
6042
|
-
require_transform.assertScope(() => active);
|
|
6043
|
-
return inputAccess(target, requester).read();
|
|
6044
|
-
};
|
|
6045
|
-
try {
|
|
6046
|
-
return run(read);
|
|
6047
|
-
} finally {
|
|
6048
|
-
active = false;
|
|
6049
|
-
}
|
|
6050
|
-
}, options);
|
|
6266
|
+
const batch = (run, options) => scheduler.batch(run, options);
|
|
6051
6267
|
const disposeScope = (state) => {
|
|
6052
6268
|
if (!state.active) return;
|
|
6053
6269
|
scheduler.assertIdle();
|
|
@@ -6139,7 +6355,7 @@ const createProjectionRuntime = (options) => {
|
|
|
6139
6355
|
}
|
|
6140
6356
|
function scopeBatch(run, options) {
|
|
6141
6357
|
assertActive();
|
|
6142
|
-
return batch(run, options
|
|
6358
|
+
return batch(run, options);
|
|
6143
6359
|
}
|
|
6144
6360
|
return Object.freeze({
|
|
6145
6361
|
own,
|