@expressive/mvc 0.4.3 → 0.4.6
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/lib/index.d.ts +12 -7
- package/lib/index.esm.js +122 -201
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +123 -201
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -172,11 +172,10 @@ const Oops$a = issues({
|
|
|
172
172
|
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
173
173
|
});
|
|
174
174
|
const INFO = new WeakMap();
|
|
175
|
-
const USED = new WeakMap();
|
|
176
175
|
const KEYS = new WeakMap();
|
|
177
|
-
|
|
176
|
+
const ORDER = new WeakMap();
|
|
177
|
+
function get(source, arg1, arg2) {
|
|
178
178
|
return apply(function from(key) {
|
|
179
|
-
const parent = this;
|
|
180
179
|
const { subject, state } = this;
|
|
181
180
|
const required = arg2 === true || arg1 === true;
|
|
182
181
|
let getSource;
|
|
@@ -197,14 +196,13 @@ function from(source, arg1, arg2) {
|
|
|
197
196
|
else
|
|
198
197
|
throw Oops$a.BadSource(subject, key, source);
|
|
199
198
|
const setter = arg1;
|
|
200
|
-
const info = { key, parent
|
|
199
|
+
const info = { key, parent: this };
|
|
201
200
|
let sub;
|
|
202
|
-
let
|
|
203
|
-
if (!
|
|
204
|
-
|
|
201
|
+
let order = ORDER.get(this);
|
|
202
|
+
if (!order)
|
|
203
|
+
ORDER.set(this, order = []);
|
|
205
204
|
state.set(key, undefined);
|
|
206
|
-
|
|
207
|
-
function compute(initial) {
|
|
205
|
+
const compute = (initial) => {
|
|
208
206
|
try {
|
|
209
207
|
return setter.call(sub.proxy, sub.proxy);
|
|
210
208
|
}
|
|
@@ -212,8 +210,8 @@ function from(source, arg1, arg2) {
|
|
|
212
210
|
Oops$a.Failed(subject, key, initial).warn();
|
|
213
211
|
throw err;
|
|
214
212
|
}
|
|
215
|
-
}
|
|
216
|
-
|
|
213
|
+
};
|
|
214
|
+
const refreshValue = () => {
|
|
217
215
|
let value;
|
|
218
216
|
try {
|
|
219
217
|
value = compute(false);
|
|
@@ -223,26 +221,25 @@ function from(source, arg1, arg2) {
|
|
|
223
221
|
}
|
|
224
222
|
finally {
|
|
225
223
|
if (state.get(key) !== value) {
|
|
226
|
-
|
|
227
|
-
|
|
224
|
+
state.set(key, value);
|
|
225
|
+
this.update(key);
|
|
228
226
|
return value;
|
|
229
227
|
}
|
|
230
228
|
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (info.parent !== from)
|
|
237
|
-
update();
|
|
238
|
-
else {
|
|
239
|
-
const after = pending.findIndex(peer => (info.priority > INFO.get(peer).priority));
|
|
240
|
-
pending.splice(after + 1, 0, update);
|
|
229
|
+
};
|
|
230
|
+
const dependancyDidUpdate = (_key, source) => {
|
|
231
|
+
if (source !== this) {
|
|
232
|
+
refreshValue();
|
|
233
|
+
return;
|
|
241
234
|
}
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
let pending = KEYS.get(this);
|
|
236
|
+
if (!pending)
|
|
237
|
+
KEYS.set(this, pending = []);
|
|
238
|
+
pending.push(refreshValue);
|
|
239
|
+
};
|
|
240
|
+
const create = () => {
|
|
244
241
|
const control = getSource();
|
|
245
|
-
sub = control.subscribe(
|
|
242
|
+
sub = control.subscribe(dependancyDidUpdate);
|
|
246
243
|
try {
|
|
247
244
|
const value = compute(true);
|
|
248
245
|
state.set(key, value);
|
|
@@ -253,14 +250,10 @@ function from(source, arg1, arg2) {
|
|
|
253
250
|
}
|
|
254
251
|
finally {
|
|
255
252
|
sub.commit();
|
|
256
|
-
|
|
257
|
-
const peer = register.get(key);
|
|
258
|
-
if (peer && peer.priority >= info.priority)
|
|
259
|
-
info.priority = peer.priority + 1;
|
|
260
|
-
}
|
|
253
|
+
order.push(refreshValue);
|
|
261
254
|
}
|
|
262
|
-
}
|
|
263
|
-
INFO.set(
|
|
255
|
+
};
|
|
256
|
+
INFO.set(refreshValue, info);
|
|
264
257
|
return () => {
|
|
265
258
|
const value = sub ? state.get(key) : create();
|
|
266
259
|
if (value === undefined && required)
|
|
@@ -273,8 +266,11 @@ function flush(control) {
|
|
|
273
266
|
const pending = KEYS.get(control);
|
|
274
267
|
if (!pending)
|
|
275
268
|
return;
|
|
269
|
+
const list = ORDER.get(control);
|
|
276
270
|
while (pending.length) {
|
|
277
|
-
const compute = pending
|
|
271
|
+
const compute = pending
|
|
272
|
+
.sort((a, b) => list.indexOf(b) - list.indexOf(a))
|
|
273
|
+
.pop();
|
|
278
274
|
const { key } = INFO.get(compute);
|
|
279
275
|
if (!control.frame.has(key))
|
|
280
276
|
compute();
|
|
@@ -299,18 +295,16 @@ class Subscriber {
|
|
|
299
295
|
}
|
|
300
296
|
});
|
|
301
297
|
const release = parent.addListener(key => {
|
|
302
|
-
if (!this.active
|
|
298
|
+
if (!this.active)
|
|
303
299
|
return;
|
|
304
300
|
const handler = using.get(key);
|
|
305
301
|
let notify;
|
|
306
302
|
if (typeof handler == "function") {
|
|
307
303
|
const callback = handler();
|
|
308
|
-
if (
|
|
309
|
-
notify = callback;
|
|
310
|
-
else if (callback === true)
|
|
304
|
+
if (callback === true)
|
|
311
305
|
notify = this.onUpdate(key, parent);
|
|
312
306
|
}
|
|
313
|
-
else
|
|
307
|
+
else if (handler === true)
|
|
314
308
|
notify = this.onUpdate(key, parent);
|
|
315
309
|
const getWhy = () => {
|
|
316
310
|
const update = getUpdate(parent.subject);
|
|
@@ -332,7 +326,7 @@ class Subscriber {
|
|
|
332
326
|
release();
|
|
333
327
|
};
|
|
334
328
|
this.add = (key, value) => {
|
|
335
|
-
if (value)
|
|
329
|
+
if (value !== undefined)
|
|
336
330
|
using.set(key, value);
|
|
337
331
|
else if (!using.has(key))
|
|
338
332
|
using.set(key, true);
|
|
@@ -406,17 +400,15 @@ class Controller {
|
|
|
406
400
|
else if (!frame.size)
|
|
407
401
|
setTimeout(() => {
|
|
408
402
|
flush(this);
|
|
409
|
-
|
|
410
|
-
const keys = Array.from(frame);
|
|
411
|
-
frame.clear();
|
|
412
|
-
waiting.clear();
|
|
413
|
-
UPDATE.set(subject, keys);
|
|
403
|
+
UPDATE.set(subject, Array.from(frame));
|
|
414
404
|
setTimeout(() => {
|
|
415
405
|
UPDATE.delete(subject);
|
|
416
406
|
}, 0);
|
|
417
|
-
|
|
407
|
+
frame.clear();
|
|
408
|
+
for (const notify of waiting)
|
|
418
409
|
try {
|
|
419
|
-
|
|
410
|
+
waiting.delete(notify);
|
|
411
|
+
notify();
|
|
420
412
|
}
|
|
421
413
|
catch (err) {
|
|
422
414
|
console.error(err);
|
|
@@ -667,6 +659,14 @@ function apply(fn, label) {
|
|
|
667
659
|
const desc = output;
|
|
668
660
|
if ("value" in desc)
|
|
669
661
|
state.set(key, desc.value);
|
|
662
|
+
if ("destroy" in output) {
|
|
663
|
+
const { destroy } = output;
|
|
664
|
+
if (destroy)
|
|
665
|
+
this.addListener((key) => {
|
|
666
|
+
if (key == null)
|
|
667
|
+
destroy();
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
670
|
const { get: onGet, set: onSet, enumerable, suspense } = desc;
|
|
671
671
|
const set = onSet !== false
|
|
672
672
|
? this.ref(key, onSet)
|
|
@@ -944,172 +944,100 @@ function parent(Expects, required) {
|
|
|
944
944
|
});
|
|
945
945
|
}
|
|
946
946
|
|
|
947
|
-
const ANY
|
|
948
|
-
function
|
|
949
|
-
const managed = new
|
|
947
|
+
const ANY = Symbol("any");
|
|
948
|
+
function keyed(control, property, initial) {
|
|
949
|
+
const managed = new Stateful(initial, emit);
|
|
950
950
|
const context = new WeakMap();
|
|
951
|
-
const
|
|
951
|
+
const observers = new Set();
|
|
952
|
+
const frozen = new Set();
|
|
952
953
|
function reset() {
|
|
953
|
-
|
|
954
|
+
frozen.clear();
|
|
954
955
|
}
|
|
955
956
|
function emit(key) {
|
|
956
|
-
lastUpdate.add(key);
|
|
957
|
-
control.update(property);
|
|
958
957
|
control.waiting.add(reset);
|
|
958
|
+
control.update(property);
|
|
959
|
+
observers.forEach(notify => notify(key));
|
|
959
960
|
}
|
|
960
|
-
function
|
|
961
|
-
control.state.set(property, next);
|
|
962
|
-
managed.source = next;
|
|
963
|
-
emit(ANY$1);
|
|
964
|
-
}
|
|
965
|
-
function getValue(local) {
|
|
966
|
-
if (!local)
|
|
967
|
-
return managed;
|
|
968
|
-
if (context.has(local))
|
|
969
|
-
return context.get(local);
|
|
970
|
-
const refresh = local.onUpdate(property, control);
|
|
961
|
+
function init(local) {
|
|
971
962
|
const proxy = create(managed);
|
|
972
963
|
const using = new Set();
|
|
973
|
-
|
|
974
|
-
if (
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
964
|
+
function onEvent(key) {
|
|
965
|
+
if (frozen.has(local))
|
|
966
|
+
return;
|
|
967
|
+
if (key === ANY || using.has(key) || using.has(ANY)) {
|
|
968
|
+
const refresh = local.onUpdate(property, control);
|
|
969
|
+
if (refresh) {
|
|
970
|
+
frozen.add(local);
|
|
971
|
+
refresh();
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
984
975
|
context.set(local, proxy);
|
|
985
976
|
proxy.watch = (key) => {
|
|
986
977
|
if (!local.active)
|
|
987
978
|
using.add(key);
|
|
988
979
|
};
|
|
980
|
+
local.add(property, false);
|
|
981
|
+
local.dependant.add({
|
|
982
|
+
commit() {
|
|
983
|
+
if (using.size === 0)
|
|
984
|
+
using.add(ANY);
|
|
985
|
+
observers.add(onEvent);
|
|
986
|
+
},
|
|
987
|
+
release() {
|
|
988
|
+
observers.delete(onEvent);
|
|
989
|
+
}
|
|
990
|
+
});
|
|
989
991
|
return proxy;
|
|
990
992
|
}
|
|
991
993
|
return {
|
|
992
994
|
value: initial,
|
|
993
|
-
|
|
994
|
-
|
|
995
|
+
get(local) {
|
|
996
|
+
return local ?
|
|
997
|
+
context.get(local) || init(local) :
|
|
998
|
+
managed;
|
|
999
|
+
},
|
|
1000
|
+
set(next) {
|
|
1001
|
+
managed.source = next;
|
|
1002
|
+
control.state.set(property, next);
|
|
1003
|
+
emit(ANY);
|
|
1004
|
+
},
|
|
1005
|
+
destroy() {
|
|
1006
|
+
observers.clear();
|
|
1007
|
+
}
|
|
995
1008
|
};
|
|
996
1009
|
}
|
|
997
|
-
class
|
|
1010
|
+
class Stateful {
|
|
998
1011
|
constructor(source, emit) {
|
|
999
1012
|
this.source = source;
|
|
1000
1013
|
this.emit = emit;
|
|
1014
|
+
if (source instanceof Set)
|
|
1015
|
+
assign(this, {
|
|
1016
|
+
add(key) {
|
|
1017
|
+
source.add(key);
|
|
1018
|
+
emit(key);
|
|
1019
|
+
return this;
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
else
|
|
1023
|
+
assign(this, {
|
|
1024
|
+
get(key) {
|
|
1025
|
+
this.watch(key);
|
|
1026
|
+
return source.get(key);
|
|
1027
|
+
},
|
|
1028
|
+
set(key, value) {
|
|
1029
|
+
source.set(key, value);
|
|
1030
|
+
emit(key);
|
|
1031
|
+
return this;
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1001
1034
|
}
|
|
1002
1035
|
watch(_key) { }
|
|
1003
|
-
set(key, value) {
|
|
1004
|
-
this.source.set(key, value);
|
|
1005
|
-
this.emit(key);
|
|
1006
|
-
return this;
|
|
1007
|
-
}
|
|
1008
|
-
;
|
|
1009
|
-
delete(key) {
|
|
1010
|
-
this.emit(key);
|
|
1011
|
-
return this.source.delete(key);
|
|
1012
|
-
}
|
|
1013
|
-
;
|
|
1014
|
-
clear() {
|
|
1015
|
-
this.emit(ANY$1);
|
|
1016
|
-
this.source.clear();
|
|
1017
|
-
}
|
|
1018
|
-
get(key) {
|
|
1019
|
-
this.watch(key);
|
|
1020
|
-
return this.source.get(key);
|
|
1021
|
-
}
|
|
1022
|
-
;
|
|
1023
1036
|
has(key) {
|
|
1024
1037
|
this.watch(key);
|
|
1025
1038
|
return this.source.has(key);
|
|
1026
1039
|
}
|
|
1027
1040
|
;
|
|
1028
|
-
values() {
|
|
1029
|
-
this.watch(ANY$1);
|
|
1030
|
-
return this.source.values();
|
|
1031
|
-
}
|
|
1032
|
-
keys() {
|
|
1033
|
-
this.watch(ANY$1);
|
|
1034
|
-
return this.source.keys();
|
|
1035
|
-
}
|
|
1036
|
-
entries() {
|
|
1037
|
-
this.watch(ANY$1);
|
|
1038
|
-
return this.source.entries();
|
|
1039
|
-
}
|
|
1040
|
-
;
|
|
1041
|
-
[Symbol.iterator]() {
|
|
1042
|
-
this.watch(ANY$1);
|
|
1043
|
-
return this.source[Symbol.iterator]();
|
|
1044
|
-
}
|
|
1045
|
-
;
|
|
1046
|
-
get size() {
|
|
1047
|
-
this.watch(ANY$1);
|
|
1048
|
-
return this.source.size;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
const ANY = Symbol("any");
|
|
1053
|
-
function managedSet(control, property, initial) {
|
|
1054
|
-
const managed = new ManagedSet(initial, emit);
|
|
1055
|
-
const context = new WeakMap();
|
|
1056
|
-
const lastUpdate = new Set();
|
|
1057
|
-
function reset() {
|
|
1058
|
-
lastUpdate.clear();
|
|
1059
|
-
}
|
|
1060
|
-
function emit(key) {
|
|
1061
|
-
lastUpdate.add(key);
|
|
1062
|
-
control.update(property);
|
|
1063
|
-
control.waiting.add(reset);
|
|
1064
|
-
}
|
|
1065
|
-
function setValue(next) {
|
|
1066
|
-
managed.source = next;
|
|
1067
|
-
control.state.set(property, next);
|
|
1068
|
-
emit(ANY);
|
|
1069
|
-
}
|
|
1070
|
-
function getValue(local) {
|
|
1071
|
-
if (!local)
|
|
1072
|
-
return managed;
|
|
1073
|
-
if (context.has(local))
|
|
1074
|
-
return context.get(local);
|
|
1075
|
-
const refresh = local.onUpdate(property, control);
|
|
1076
|
-
const proxy = create(managed);
|
|
1077
|
-
const using = new Set();
|
|
1078
|
-
const update = () => {
|
|
1079
|
-
if (using.has(ANY) || lastUpdate.has(ANY) && using.size)
|
|
1080
|
-
refresh();
|
|
1081
|
-
else
|
|
1082
|
-
for (const key of lastUpdate)
|
|
1083
|
-
if (using.has(key)) {
|
|
1084
|
-
refresh();
|
|
1085
|
-
break;
|
|
1086
|
-
}
|
|
1087
|
-
};
|
|
1088
|
-
local.add(property, () => update);
|
|
1089
|
-
context.set(local, proxy);
|
|
1090
|
-
proxy.watch = (key) => {
|
|
1091
|
-
if (!local.active)
|
|
1092
|
-
using.add(key);
|
|
1093
|
-
};
|
|
1094
|
-
return proxy;
|
|
1095
|
-
}
|
|
1096
|
-
return {
|
|
1097
|
-
value: initial,
|
|
1098
|
-
set: setValue,
|
|
1099
|
-
get: getValue
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
class ManagedSet {
|
|
1103
|
-
constructor(source, emit) {
|
|
1104
|
-
this.source = source;
|
|
1105
|
-
this.emit = emit;
|
|
1106
|
-
}
|
|
1107
|
-
watch(_key) { }
|
|
1108
|
-
add(key) {
|
|
1109
|
-
this.emit(key);
|
|
1110
|
-
return this.source.add(key);
|
|
1111
|
-
}
|
|
1112
|
-
;
|
|
1113
1041
|
delete(key) {
|
|
1114
1042
|
this.emit(key);
|
|
1115
1043
|
return this.source.delete(key);
|
|
@@ -1119,33 +1047,28 @@ class ManagedSet {
|
|
|
1119
1047
|
this.emit(ANY);
|
|
1120
1048
|
this.source.clear();
|
|
1121
1049
|
}
|
|
1122
|
-
|
|
1123
|
-
this.watch(
|
|
1124
|
-
return this.source.
|
|
1050
|
+
keys() {
|
|
1051
|
+
this.watch(ANY);
|
|
1052
|
+
return this.source.keys();
|
|
1125
1053
|
}
|
|
1126
|
-
;
|
|
1127
1054
|
values() {
|
|
1128
1055
|
this.watch(ANY);
|
|
1129
1056
|
return this.source.values();
|
|
1130
1057
|
}
|
|
1131
|
-
keys() {
|
|
1132
|
-
this.watch(ANY);
|
|
1133
|
-
return this.source.keys();
|
|
1134
|
-
}
|
|
1135
1058
|
entries() {
|
|
1136
1059
|
this.watch(ANY);
|
|
1137
1060
|
return this.source.entries();
|
|
1138
1061
|
}
|
|
1139
1062
|
;
|
|
1063
|
+
get size() {
|
|
1064
|
+
this.watch(ANY);
|
|
1065
|
+
return this.source.size;
|
|
1066
|
+
}
|
|
1140
1067
|
[Symbol.iterator]() {
|
|
1141
1068
|
this.watch(ANY);
|
|
1142
1069
|
return this.source[Symbol.iterator]();
|
|
1143
1070
|
}
|
|
1144
1071
|
;
|
|
1145
|
-
get size() {
|
|
1146
|
-
this.watch(ANY);
|
|
1147
|
-
return this.source.size;
|
|
1148
|
-
}
|
|
1149
1072
|
}
|
|
1150
1073
|
|
|
1151
1074
|
const Oops$5 = issues({
|
|
@@ -1160,10 +1083,8 @@ function use$1(input, argument) {
|
|
|
1160
1083
|
: input();
|
|
1161
1084
|
else if (input && typeof input !== "object")
|
|
1162
1085
|
throw Oops$5.BadArgument(typeof input);
|
|
1163
|
-
if (input instanceof Map)
|
|
1164
|
-
return
|
|
1165
|
-
if (input instanceof Set)
|
|
1166
|
-
return managedSet(this, key, input);
|
|
1086
|
+
if (input instanceof Map || input instanceof Set)
|
|
1087
|
+
return keyed(this, key, input);
|
|
1167
1088
|
function onUpdate(next) {
|
|
1168
1089
|
state.set(key, next);
|
|
1169
1090
|
if (next) {
|
|
@@ -1618,7 +1539,8 @@ exports.act = act;
|
|
|
1618
1539
|
exports.apply = apply;
|
|
1619
1540
|
exports.array = array;
|
|
1620
1541
|
exports["default"] = MVC;
|
|
1621
|
-
exports.from =
|
|
1542
|
+
exports.from = get;
|
|
1543
|
+
exports.get = get;
|
|
1622
1544
|
exports.parent = parent;
|
|
1623
1545
|
exports.put = put;
|
|
1624
1546
|
exports.ref = ref;
|