@expressive/mvc 0.63.5 → 0.64.0
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/dist/esm/control.js +30 -73
- package/dist/esm/index.js +4 -3
- package/dist/esm/instruction/has.js +23 -19
- package/dist/esm/instruction/ref.js +4 -4
- package/dist/esm/instruction/set.js +17 -19
- package/dist/esm/instruction/use.js +5 -6
- package/dist/esm/model.js +65 -36
- package/dist/index.d.ts +41 -11
- package/dist/index.js +134 -143
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -23,10 +23,11 @@ __export(index_exports, {
|
|
|
23
23
|
Context: () => Context,
|
|
24
24
|
METHOD: () => METHOD,
|
|
25
25
|
Model: () => Model,
|
|
26
|
+
Observable: () => Observable,
|
|
26
27
|
addListener: () => addListener,
|
|
27
28
|
createEffect: () => createEffect,
|
|
28
|
-
createProxy: () => createProxy,
|
|
29
29
|
default: () => Model,
|
|
30
|
+
event: () => event,
|
|
30
31
|
get: () => get,
|
|
31
32
|
has: () => has,
|
|
32
33
|
ref: () => ref,
|
|
@@ -36,20 +37,21 @@ __export(index_exports, {
|
|
|
36
37
|
module.exports = __toCommonJS(index_exports);
|
|
37
38
|
|
|
38
39
|
// src/control.ts
|
|
40
|
+
var Observable = Symbol("observe");
|
|
39
41
|
var onReady = () => null;
|
|
40
42
|
var LISTENERS = /* @__PURE__ */ new WeakMap();
|
|
41
43
|
var PENDING = /* @__PURE__ */ new WeakMap();
|
|
42
44
|
var PENDING_KEYS = /* @__PURE__ */ new WeakMap();
|
|
43
45
|
var DISPATCH = /* @__PURE__ */ new Set();
|
|
44
|
-
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
45
46
|
function addListener(subject, callback, select) {
|
|
46
47
|
let listeners = LISTENERS.get(subject);
|
|
47
48
|
if (!listeners)
|
|
48
49
|
LISTENERS.set(subject, listeners = /* @__PURE__ */ new Map([[onReady, void 0]]));
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
if (select !== void 0 && !(select instanceof Set))
|
|
51
|
+
select = /* @__PURE__ */ new Set([select]);
|
|
52
|
+
if (!listeners.has(onReady) && !select)
|
|
51
53
|
callback.call(subject, true, subject);
|
|
52
|
-
listeners.set(callback,
|
|
54
|
+
listeners.set(callback, select);
|
|
53
55
|
return () => listeners.delete(callback);
|
|
54
56
|
}
|
|
55
57
|
function emit(model, key2) {
|
|
@@ -57,13 +59,13 @@ function emit(model, key2) {
|
|
|
57
59
|
const notReady = listeners.has(onReady);
|
|
58
60
|
if (key2 === true && !notReady)
|
|
59
61
|
return;
|
|
60
|
-
let
|
|
61
|
-
if (
|
|
62
|
-
|
|
62
|
+
let pending = PENDING.get(model);
|
|
63
|
+
if (pending) {
|
|
64
|
+
pending.add(key2);
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
|
-
PENDING.set(model,
|
|
66
|
-
for (const key3 of
|
|
67
|
+
PENDING.set(model, pending = new Set(notReady ? [true, key2] : [key2]));
|
|
68
|
+
for (const key3 of pending)
|
|
67
69
|
for (const [callback, filter] of listeners)
|
|
68
70
|
if (!filter || filter.has(key3)) {
|
|
69
71
|
const after = callback.call(model, key3, model);
|
|
@@ -81,32 +83,19 @@ function event(subject, key2, silent) {
|
|
|
81
83
|
return emit(subject, key2);
|
|
82
84
|
if (!key2)
|
|
83
85
|
return emit(subject, true);
|
|
84
|
-
let
|
|
85
|
-
if (!
|
|
86
|
-
PENDING_KEYS.set(subject,
|
|
86
|
+
let pending = PENDING_KEYS.get(subject);
|
|
87
|
+
if (!pending) {
|
|
88
|
+
PENDING_KEYS.set(subject, pending = /* @__PURE__ */ new Set());
|
|
87
89
|
if (!silent)
|
|
88
90
|
enqueue(() => {
|
|
89
91
|
emit(subject, false);
|
|
90
92
|
PENDING_KEYS.delete(subject);
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
|
-
|
|
95
|
+
pending.add(key2);
|
|
94
96
|
if (!silent)
|
|
95
97
|
emit(subject, key2);
|
|
96
98
|
}
|
|
97
|
-
function pending(subject) {
|
|
98
|
-
if (PENDING_KEYS.has(subject))
|
|
99
|
-
return {
|
|
100
|
-
then: (res) => new Promise((res2) => {
|
|
101
|
-
const remove = addListener(subject, (key2) => {
|
|
102
|
-
if (key2 !== true) {
|
|
103
|
-
remove();
|
|
104
|
-
return res2.bind(null, Array.from(PENDING_KEYS.get(subject)));
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}).then(res)
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
99
|
function enqueue(eventHandler) {
|
|
111
100
|
if (!DISPATCH.size)
|
|
112
101
|
setTimeout(() => {
|
|
@@ -121,23 +110,11 @@ function enqueue(eventHandler) {
|
|
|
121
110
|
}, 0);
|
|
122
111
|
DISPATCH.add(eventHandler);
|
|
123
112
|
}
|
|
124
|
-
function createProxy(from, observer) {
|
|
125
|
-
const proxy = Object.create(from);
|
|
126
|
-
OBSERVER.set(proxy, observer);
|
|
127
|
-
return proxy;
|
|
128
|
-
}
|
|
129
|
-
function watch(from, key2, value) {
|
|
130
|
-
const access = OBSERVER.get(from);
|
|
131
|
-
return access ? access(from, key2, value) : value;
|
|
132
|
-
}
|
|
133
113
|
function createEffect(target, callback, argument) {
|
|
134
|
-
const listeners = LISTENERS.get(target);
|
|
135
114
|
let unset;
|
|
136
115
|
let reset;
|
|
137
116
|
function invoke() {
|
|
138
117
|
let stale;
|
|
139
|
-
const subscriber = createProxy(target, access);
|
|
140
|
-
LISTENERS.set(subscriber, listeners);
|
|
141
118
|
function onUpdate() {
|
|
142
119
|
if (stale)
|
|
143
120
|
return null;
|
|
@@ -148,30 +125,15 @@ function createEffect(target, callback, argument) {
|
|
|
148
125
|
}
|
|
149
126
|
return reset;
|
|
150
127
|
}
|
|
151
|
-
|
|
152
|
-
if (value === void 0 && argument)
|
|
153
|
-
throw new Error(`${from}.${key2} is required in this context.`);
|
|
154
|
-
const listeners2 = LISTENERS.get(from);
|
|
155
|
-
let listener = listeners2.get(onUpdate);
|
|
156
|
-
if (!listener)
|
|
157
|
-
listeners2.set(onUpdate, listener = /* @__PURE__ */ new Set());
|
|
158
|
-
listener.add(key2);
|
|
159
|
-
const nested = LISTENERS.get(value);
|
|
160
|
-
if (nested)
|
|
161
|
-
LISTENERS.set(
|
|
162
|
-
value = createProxy(value, access),
|
|
163
|
-
nested
|
|
164
|
-
);
|
|
165
|
-
return value;
|
|
166
|
-
}
|
|
128
|
+
const subscriber = target[Observable](onUpdate, argument === true);
|
|
167
129
|
try {
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
const flush =
|
|
171
|
-
reset =
|
|
130
|
+
const exit = enter(argument === false);
|
|
131
|
+
const output = callback.call(subscriber, subscriber);
|
|
132
|
+
const flush = exit();
|
|
133
|
+
reset = output === null ? null : invoke;
|
|
172
134
|
unset = (key2) => {
|
|
173
|
-
if (typeof
|
|
174
|
-
|
|
135
|
+
if (typeof output == "function")
|
|
136
|
+
output(key2);
|
|
175
137
|
flush();
|
|
176
138
|
};
|
|
177
139
|
} catch (err) {
|
|
@@ -201,17 +163,15 @@ function createEffect(target, callback, argument) {
|
|
|
201
163
|
return cleanup;
|
|
202
164
|
}
|
|
203
165
|
var EffectContext;
|
|
204
|
-
function
|
|
166
|
+
function enter(ignore) {
|
|
205
167
|
if (ignore)
|
|
206
168
|
return () => () => {
|
|
207
169
|
};
|
|
208
|
-
const
|
|
209
|
-
const
|
|
170
|
+
const last = EffectContext;
|
|
171
|
+
const context = EffectContext = /* @__PURE__ */ new Set();
|
|
210
172
|
return () => {
|
|
211
|
-
EffectContext =
|
|
212
|
-
return () =>
|
|
213
|
-
ctx.forEach((fn) => fn());
|
|
214
|
-
};
|
|
173
|
+
EffectContext = last;
|
|
174
|
+
return () => context.forEach((fn) => fn());
|
|
215
175
|
};
|
|
216
176
|
}
|
|
217
177
|
|
|
@@ -229,14 +189,28 @@ var Model = class {
|
|
|
229
189
|
define(this, "is", { value: this });
|
|
230
190
|
init(this, args);
|
|
231
191
|
}
|
|
192
|
+
[Observable](callback, required) {
|
|
193
|
+
const watch2 = /* @__PURE__ */ new Set();
|
|
194
|
+
const proxy = Object.create(this);
|
|
195
|
+
addListener(this, callback, watch2);
|
|
196
|
+
OBSERVER.set(proxy, (key2, value) => {
|
|
197
|
+
if (value === void 0 && required)
|
|
198
|
+
throw new Error(`${this}.${key2} is required in this context.`);
|
|
199
|
+
watch2.add(key2);
|
|
200
|
+
if (value instanceof Object && Observable in value)
|
|
201
|
+
return value[Observable](callback, required);
|
|
202
|
+
return value;
|
|
203
|
+
});
|
|
204
|
+
return proxy;
|
|
205
|
+
}
|
|
232
206
|
get(arg1, arg2) {
|
|
233
207
|
const self = this.is;
|
|
234
208
|
if (typeof arg1 == "function") {
|
|
235
|
-
let
|
|
209
|
+
let pending = /* @__PURE__ */ new Set();
|
|
236
210
|
return createEffect(self, (proxy) => {
|
|
237
|
-
const cb = arg1.call(proxy, proxy,
|
|
211
|
+
const cb = arg1.call(proxy, proxy, pending);
|
|
238
212
|
return cb === null ? null : (update2) => {
|
|
239
|
-
|
|
213
|
+
pending = PENDING_KEYS.get(self);
|
|
240
214
|
if (typeof cb == "function")
|
|
241
215
|
cb(update2);
|
|
242
216
|
};
|
|
@@ -244,23 +218,33 @@ var Model = class {
|
|
|
244
218
|
}
|
|
245
219
|
return arg1 === void 0 ? snapshot(self) : typeof arg2 == "function" ? addListener(self, arg2, arg1) : arg1 === null ? Object.isFrozen(STATE.get(self)) : fetch(self, arg1, arg2);
|
|
246
220
|
}
|
|
247
|
-
set(arg1, arg2) {
|
|
221
|
+
set(arg1, arg2, arg3) {
|
|
248
222
|
const self = this.is;
|
|
249
223
|
if (typeof arg1 == "function")
|
|
250
224
|
return addListener(self, (key2) => {
|
|
251
|
-
if (typeof key2 == "string")
|
|
225
|
+
if (arg2 === key2 || arg2 === void 0 && typeof key2 == "string")
|
|
252
226
|
return arg1.call(self, key2, self);
|
|
253
227
|
});
|
|
254
|
-
if (typeof arg2 == "function")
|
|
255
|
-
return addListener(self, (key2) => {
|
|
256
|
-
if (key2 === arg1)
|
|
257
|
-
return arg2.call(self, key2, self);
|
|
258
|
-
});
|
|
259
228
|
if (arg1 && typeof arg1 == "object")
|
|
260
229
|
assign(self, arg1, arg2 === true);
|
|
261
|
-
else
|
|
230
|
+
else if (!arg2)
|
|
262
231
|
event(self, arg1);
|
|
263
|
-
|
|
232
|
+
else if (arg3)
|
|
233
|
+
manage(self, arg1, arg2);
|
|
234
|
+
else
|
|
235
|
+
update(self, arg1, arg2);
|
|
236
|
+
const pending = PENDING_KEYS.get(this);
|
|
237
|
+
if (pending)
|
|
238
|
+
return {
|
|
239
|
+
then: (res) => new Promise((res2) => {
|
|
240
|
+
const remove = addListener(this, (key2) => {
|
|
241
|
+
if (key2 !== true) {
|
|
242
|
+
remove();
|
|
243
|
+
return res2.bind(null, Array.from(pending));
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}).then(res)
|
|
247
|
+
};
|
|
264
248
|
}
|
|
265
249
|
/**
|
|
266
250
|
* Iterate over managed properties in this instance of Model.
|
|
@@ -320,7 +304,7 @@ function assign(subject, data, silent) {
|
|
|
320
304
|
else if (key2 in subject && key2 !== "is") {
|
|
321
305
|
const desc = Object.getOwnPropertyDescriptor(subject, key2);
|
|
322
306
|
const set2 = desc && desc.set;
|
|
323
|
-
set2.call(subject, data[key2], silent
|
|
307
|
+
set2.call(subject, data[key2], silent);
|
|
324
308
|
}
|
|
325
309
|
}
|
|
326
310
|
}
|
|
@@ -378,26 +362,10 @@ function init(model, args) {
|
|
|
378
362
|
PARENT.set(model, null);
|
|
379
363
|
for (const key2 in model) {
|
|
380
364
|
const desc = Object.getOwnPropertyDescriptor(model, key2);
|
|
381
|
-
if ("value" in desc)
|
|
382
|
-
|
|
383
|
-
update(model, key2, value, silent);
|
|
384
|
-
if (value instanceof Model && !PARENT.has(value)) {
|
|
385
|
-
PARENT.set(value, model);
|
|
386
|
-
event(value);
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
var set2 = set3;
|
|
390
|
-
set3(desc.value, true);
|
|
391
|
-
define(model, key2, {
|
|
392
|
-
configurable: false,
|
|
393
|
-
set: set3,
|
|
394
|
-
get() {
|
|
395
|
-
return watch(this, key2, state[key2]);
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
}
|
|
365
|
+
if ("value" in desc)
|
|
366
|
+
manage(model, key2, desc.value, true);
|
|
399
367
|
}
|
|
400
|
-
|
|
368
|
+
for (const arg of args) {
|
|
401
369
|
const use2 = typeof arg == "function" ? arg.call(model, model) : arg;
|
|
402
370
|
if (use2 instanceof Promise)
|
|
403
371
|
use2.catch((err) => {
|
|
@@ -408,7 +376,7 @@ function init(model, args) {
|
|
|
408
376
|
addListener(model, use2, null);
|
|
409
377
|
else if (typeof use2 == "object")
|
|
410
378
|
assign(model, use2, true);
|
|
411
|
-
}
|
|
379
|
+
}
|
|
412
380
|
addListener(model, () => {
|
|
413
381
|
for (const [_, value] of model)
|
|
414
382
|
if (value instanceof Model && PARENT.get(value) === model)
|
|
@@ -418,6 +386,26 @@ function init(model, args) {
|
|
|
418
386
|
return null;
|
|
419
387
|
});
|
|
420
388
|
}
|
|
389
|
+
function manage(target, key2, value, silent) {
|
|
390
|
+
const state = STATE.get(target);
|
|
391
|
+
function get2() {
|
|
392
|
+
return watch(this, key2, state[key2]);
|
|
393
|
+
}
|
|
394
|
+
function set2(value2, silent2) {
|
|
395
|
+
update(target, key2, value2, silent2);
|
|
396
|
+
if (value2 instanceof Model && !PARENT.has(value2)) {
|
|
397
|
+
PARENT.set(value2, target);
|
|
398
|
+
event(value2);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
define(target, key2, { set: set2, get: get2 });
|
|
402
|
+
set2(value, silent);
|
|
403
|
+
}
|
|
404
|
+
var OBSERVER = /* @__PURE__ */ new WeakMap();
|
|
405
|
+
function watch(from, key2, value) {
|
|
406
|
+
const access = OBSERVER.get(from);
|
|
407
|
+
return access ? access(key2, value) : value;
|
|
408
|
+
}
|
|
421
409
|
function fetch(subject, property, required) {
|
|
422
410
|
const state = STATE.get(subject);
|
|
423
411
|
if (property in state || required === false) {
|
|
@@ -633,13 +621,13 @@ var Context = class _Context {
|
|
|
633
621
|
// src/instruction/use.ts
|
|
634
622
|
var INSTRUCTION = /* @__PURE__ */ new Map();
|
|
635
623
|
function use(arg1, arg2) {
|
|
636
|
-
const token = Symbol("instruction-" + uid());
|
|
637
624
|
if (Model.is(arg1))
|
|
638
|
-
arg1 =
|
|
625
|
+
arg1 = childInstruction(arg1, arg2);
|
|
626
|
+
const token = Symbol("instruction-" + uid());
|
|
639
627
|
INSTRUCTION.set(token, arg1);
|
|
640
628
|
return token;
|
|
641
629
|
}
|
|
642
|
-
function
|
|
630
|
+
function childInstruction(type, arg2) {
|
|
643
631
|
return (key2, subject) => {
|
|
644
632
|
function set2(next) {
|
|
645
633
|
if (next ? !(next instanceof type) : arg2 !== false)
|
|
@@ -715,8 +703,8 @@ function get(arg0, arg1) {
|
|
|
715
703
|
} else if (arg1 === true)
|
|
716
704
|
throw new Error(`New ${subject} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
|
|
717
705
|
}
|
|
718
|
-
Context.get(subject, (
|
|
719
|
-
const model =
|
|
706
|
+
Context.get(subject, (context) => {
|
|
707
|
+
const model = context.get(arg0);
|
|
720
708
|
if (model)
|
|
721
709
|
assign3(model);
|
|
722
710
|
else if (arg1 !== false)
|
|
@@ -818,9 +806,9 @@ function ref(arg, arg2) {
|
|
|
818
806
|
unset = void unset(value2);
|
|
819
807
|
if (value2 === null && arg2 !== false)
|
|
820
808
|
return;
|
|
821
|
-
const
|
|
809
|
+
const exit = enter();
|
|
822
810
|
const out = arg.call(subject, value2);
|
|
823
|
-
const flush =
|
|
811
|
+
const flush = exit();
|
|
824
812
|
unset = (key3) => {
|
|
825
813
|
if (typeof out == "function")
|
|
826
814
|
out(key3);
|
|
@@ -851,18 +839,16 @@ function set(value, argument) {
|
|
|
851
839
|
throw err;
|
|
852
840
|
}
|
|
853
841
|
property.get = argument !== false;
|
|
842
|
+
const set2 = (value2) => subject[key2] = value2;
|
|
854
843
|
if (value instanceof Promise)
|
|
855
|
-
value.then(
|
|
856
|
-
(
|
|
857
|
-
(
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
};
|
|
862
|
-
}
|
|
863
|
-
);
|
|
844
|
+
value.then(set2, (error) => {
|
|
845
|
+
event(subject, key2);
|
|
846
|
+
property.get = () => {
|
|
847
|
+
throw error;
|
|
848
|
+
};
|
|
849
|
+
});
|
|
864
850
|
else
|
|
865
|
-
|
|
851
|
+
set2(value);
|
|
866
852
|
if (argument)
|
|
867
853
|
return null;
|
|
868
854
|
return subject[key2];
|
|
@@ -877,16 +863,16 @@ function set(value, argument) {
|
|
|
877
863
|
if (typeof argument == "function") {
|
|
878
864
|
let unset;
|
|
879
865
|
property.set = function(value2, previous) {
|
|
880
|
-
const
|
|
881
|
-
const
|
|
882
|
-
const flush =
|
|
883
|
-
if (
|
|
884
|
-
return
|
|
866
|
+
const exit = enter();
|
|
867
|
+
const returns = argument.call(this, value2, previous);
|
|
868
|
+
const flush = exit();
|
|
869
|
+
if (returns === false)
|
|
870
|
+
return false;
|
|
885
871
|
if (typeof unset == "function")
|
|
886
872
|
unset(value2);
|
|
887
873
|
unset = (next) => {
|
|
888
|
-
if (typeof
|
|
889
|
-
|
|
874
|
+
if (typeof returns == "function")
|
|
875
|
+
returns(next);
|
|
890
876
|
flush();
|
|
891
877
|
};
|
|
892
878
|
};
|
|
@@ -927,27 +913,31 @@ function has(arg1, arg2) {
|
|
|
927
913
|
if (Model.is(arg1))
|
|
928
914
|
Context.get(subject, (ctx) => {
|
|
929
915
|
ctx.has(arg1, (model) => {
|
|
930
|
-
const ctx2 = context();
|
|
931
916
|
let remove;
|
|
932
917
|
let disconnect;
|
|
918
|
+
let flush;
|
|
933
919
|
if (applied.has(model))
|
|
934
920
|
return;
|
|
935
|
-
const
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
if (
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
if (
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
921
|
+
const exit = enter();
|
|
922
|
+
try {
|
|
923
|
+
const notify = APPLY.get(model);
|
|
924
|
+
if (notify) {
|
|
925
|
+
const after = notify(subject);
|
|
926
|
+
if (after === false)
|
|
927
|
+
return;
|
|
928
|
+
if (typeof after == "function")
|
|
929
|
+
disconnect = after;
|
|
930
|
+
}
|
|
931
|
+
if (typeof arg2 == "function") {
|
|
932
|
+
const done2 = arg2(model, subject);
|
|
933
|
+
if (done2 === false)
|
|
934
|
+
return false;
|
|
935
|
+
if (typeof done2 == "function")
|
|
936
|
+
remove = done2;
|
|
937
|
+
}
|
|
938
|
+
} finally {
|
|
939
|
+
flush = exit();
|
|
949
940
|
}
|
|
950
|
-
const flush = ctx2();
|
|
951
941
|
applied.add(model);
|
|
952
942
|
reset();
|
|
953
943
|
const done = () => {
|
|
@@ -961,7 +951,7 @@ function has(arg1, arg2) {
|
|
|
961
951
|
remove();
|
|
962
952
|
remove = void 0;
|
|
963
953
|
};
|
|
964
|
-
const ignore = model.set(
|
|
954
|
+
const ignore = model.set(done, null);
|
|
965
955
|
return done;
|
|
966
956
|
});
|
|
967
957
|
});
|
|
@@ -993,9 +983,10 @@ function has(arg1, arg2) {
|
|
|
993
983
|
Context,
|
|
994
984
|
METHOD,
|
|
995
985
|
Model,
|
|
986
|
+
Observable,
|
|
996
987
|
addListener,
|
|
997
988
|
createEffect,
|
|
998
|
-
|
|
989
|
+
event,
|
|
999
990
|
get,
|
|
1000
991
|
has,
|
|
1001
992
|
ref,
|