@expressive/mvc 0.63.6 → 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 -70
- 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 +9 -9
- package/dist/esm/instruction/use.js +5 -6
- package/dist/esm/model.js +65 -36
- package/dist/index.d.ts +31 -11
- package/dist/index.js +126 -130
- 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,27 +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(value = createProxy(value, access), nested);
|
|
162
|
-
return value;
|
|
163
|
-
}
|
|
128
|
+
const subscriber = target[Observable](onUpdate, argument === true);
|
|
164
129
|
try {
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
const flush =
|
|
168
|
-
reset =
|
|
130
|
+
const exit = enter(argument === false);
|
|
131
|
+
const output = callback.call(subscriber, subscriber);
|
|
132
|
+
const flush = exit();
|
|
133
|
+
reset = output === null ? null : invoke;
|
|
169
134
|
unset = (key2) => {
|
|
170
|
-
if (typeof
|
|
171
|
-
|
|
135
|
+
if (typeof output == "function")
|
|
136
|
+
output(key2);
|
|
172
137
|
flush();
|
|
173
138
|
};
|
|
174
139
|
} catch (err) {
|
|
@@ -198,17 +163,15 @@ function createEffect(target, callback, argument) {
|
|
|
198
163
|
return cleanup;
|
|
199
164
|
}
|
|
200
165
|
var EffectContext;
|
|
201
|
-
function
|
|
166
|
+
function enter(ignore) {
|
|
202
167
|
if (ignore)
|
|
203
168
|
return () => () => {
|
|
204
169
|
};
|
|
205
|
-
const
|
|
206
|
-
const
|
|
170
|
+
const last = EffectContext;
|
|
171
|
+
const context = EffectContext = /* @__PURE__ */ new Set();
|
|
207
172
|
return () => {
|
|
208
|
-
EffectContext =
|
|
209
|
-
return () =>
|
|
210
|
-
ctx.forEach((fn) => fn());
|
|
211
|
-
};
|
|
173
|
+
EffectContext = last;
|
|
174
|
+
return () => context.forEach((fn) => fn());
|
|
212
175
|
};
|
|
213
176
|
}
|
|
214
177
|
|
|
@@ -226,14 +189,28 @@ var Model = class {
|
|
|
226
189
|
define(this, "is", { value: this });
|
|
227
190
|
init(this, args);
|
|
228
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
|
+
}
|
|
229
206
|
get(arg1, arg2) {
|
|
230
207
|
const self = this.is;
|
|
231
208
|
if (typeof arg1 == "function") {
|
|
232
|
-
let
|
|
209
|
+
let pending = /* @__PURE__ */ new Set();
|
|
233
210
|
return createEffect(self, (proxy) => {
|
|
234
|
-
const cb = arg1.call(proxy, proxy,
|
|
211
|
+
const cb = arg1.call(proxy, proxy, pending);
|
|
235
212
|
return cb === null ? null : (update2) => {
|
|
236
|
-
|
|
213
|
+
pending = PENDING_KEYS.get(self);
|
|
237
214
|
if (typeof cb == "function")
|
|
238
215
|
cb(update2);
|
|
239
216
|
};
|
|
@@ -241,23 +218,33 @@ var Model = class {
|
|
|
241
218
|
}
|
|
242
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);
|
|
243
220
|
}
|
|
244
|
-
set(arg1, arg2) {
|
|
221
|
+
set(arg1, arg2, arg3) {
|
|
245
222
|
const self = this.is;
|
|
246
223
|
if (typeof arg1 == "function")
|
|
247
224
|
return addListener(self, (key2) => {
|
|
248
|
-
if (typeof key2 == "string")
|
|
225
|
+
if (arg2 === key2 || arg2 === void 0 && typeof key2 == "string")
|
|
249
226
|
return arg1.call(self, key2, self);
|
|
250
227
|
});
|
|
251
|
-
if (typeof arg2 == "function")
|
|
252
|
-
return addListener(self, (key2) => {
|
|
253
|
-
if (key2 === arg1)
|
|
254
|
-
return arg2.call(self, key2, self);
|
|
255
|
-
});
|
|
256
228
|
if (arg1 && typeof arg1 == "object")
|
|
257
229
|
assign(self, arg1, arg2 === true);
|
|
258
|
-
else
|
|
230
|
+
else if (!arg2)
|
|
259
231
|
event(self, arg1);
|
|
260
|
-
|
|
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
|
+
};
|
|
261
248
|
}
|
|
262
249
|
/**
|
|
263
250
|
* Iterate over managed properties in this instance of Model.
|
|
@@ -317,7 +304,7 @@ function assign(subject, data, silent) {
|
|
|
317
304
|
else if (key2 in subject && key2 !== "is") {
|
|
318
305
|
const desc = Object.getOwnPropertyDescriptor(subject, key2);
|
|
319
306
|
const set2 = desc && desc.set;
|
|
320
|
-
set2.call(subject, data[key2], silent
|
|
307
|
+
set2.call(subject, data[key2], silent);
|
|
321
308
|
}
|
|
322
309
|
}
|
|
323
310
|
}
|
|
@@ -375,26 +362,10 @@ function init(model, args) {
|
|
|
375
362
|
PARENT.set(model, null);
|
|
376
363
|
for (const key2 in model) {
|
|
377
364
|
const desc = Object.getOwnPropertyDescriptor(model, key2);
|
|
378
|
-
if ("value" in desc)
|
|
379
|
-
|
|
380
|
-
update(model, key2, value, silent);
|
|
381
|
-
if (value instanceof Model && !PARENT.has(value)) {
|
|
382
|
-
PARENT.set(value, model);
|
|
383
|
-
event(value);
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
var set2 = set3;
|
|
387
|
-
set3(desc.value, true);
|
|
388
|
-
define(model, key2, {
|
|
389
|
-
configurable: false,
|
|
390
|
-
set: set3,
|
|
391
|
-
get() {
|
|
392
|
-
return watch(this, key2, state[key2]);
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
}
|
|
365
|
+
if ("value" in desc)
|
|
366
|
+
manage(model, key2, desc.value, true);
|
|
396
367
|
}
|
|
397
|
-
|
|
368
|
+
for (const arg of args) {
|
|
398
369
|
const use2 = typeof arg == "function" ? arg.call(model, model) : arg;
|
|
399
370
|
if (use2 instanceof Promise)
|
|
400
371
|
use2.catch((err) => {
|
|
@@ -405,7 +376,7 @@ function init(model, args) {
|
|
|
405
376
|
addListener(model, use2, null);
|
|
406
377
|
else if (typeof use2 == "object")
|
|
407
378
|
assign(model, use2, true);
|
|
408
|
-
}
|
|
379
|
+
}
|
|
409
380
|
addListener(model, () => {
|
|
410
381
|
for (const [_, value] of model)
|
|
411
382
|
if (value instanceof Model && PARENT.get(value) === model)
|
|
@@ -415,6 +386,26 @@ function init(model, args) {
|
|
|
415
386
|
return null;
|
|
416
387
|
});
|
|
417
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
|
+
}
|
|
418
409
|
function fetch(subject, property, required) {
|
|
419
410
|
const state = STATE.get(subject);
|
|
420
411
|
if (property in state || required === false) {
|
|
@@ -630,13 +621,13 @@ var Context = class _Context {
|
|
|
630
621
|
// src/instruction/use.ts
|
|
631
622
|
var INSTRUCTION = /* @__PURE__ */ new Map();
|
|
632
623
|
function use(arg1, arg2) {
|
|
633
|
-
const token = Symbol("instruction-" + uid());
|
|
634
624
|
if (Model.is(arg1))
|
|
635
|
-
arg1 =
|
|
625
|
+
arg1 = childInstruction(arg1, arg2);
|
|
626
|
+
const token = Symbol("instruction-" + uid());
|
|
636
627
|
INSTRUCTION.set(token, arg1);
|
|
637
628
|
return token;
|
|
638
629
|
}
|
|
639
|
-
function
|
|
630
|
+
function childInstruction(type, arg2) {
|
|
640
631
|
return (key2, subject) => {
|
|
641
632
|
function set2(next) {
|
|
642
633
|
if (next ? !(next instanceof type) : arg2 !== false)
|
|
@@ -712,8 +703,8 @@ function get(arg0, arg1) {
|
|
|
712
703
|
} else if (arg1 === true)
|
|
713
704
|
throw new Error(`New ${subject} created as child of ${hasParent}, but must be instanceof ${arg0}.`);
|
|
714
705
|
}
|
|
715
|
-
Context.get(subject, (
|
|
716
|
-
const model =
|
|
706
|
+
Context.get(subject, (context) => {
|
|
707
|
+
const model = context.get(arg0);
|
|
717
708
|
if (model)
|
|
718
709
|
assign3(model);
|
|
719
710
|
else if (arg1 !== false)
|
|
@@ -815,9 +806,9 @@ function ref(arg, arg2) {
|
|
|
815
806
|
unset = void unset(value2);
|
|
816
807
|
if (value2 === null && arg2 !== false)
|
|
817
808
|
return;
|
|
818
|
-
const
|
|
809
|
+
const exit = enter();
|
|
819
810
|
const out = arg.call(subject, value2);
|
|
820
|
-
const flush =
|
|
811
|
+
const flush = exit();
|
|
821
812
|
unset = (key3) => {
|
|
822
813
|
if (typeof out == "function")
|
|
823
814
|
out(key3);
|
|
@@ -872,16 +863,16 @@ function set(value, argument) {
|
|
|
872
863
|
if (typeof argument == "function") {
|
|
873
864
|
let unset;
|
|
874
865
|
property.set = function(value2, previous) {
|
|
875
|
-
const
|
|
876
|
-
const
|
|
877
|
-
const flush =
|
|
878
|
-
if (
|
|
879
|
-
return
|
|
866
|
+
const exit = enter();
|
|
867
|
+
const returns = argument.call(this, value2, previous);
|
|
868
|
+
const flush = exit();
|
|
869
|
+
if (returns === false)
|
|
870
|
+
return false;
|
|
880
871
|
if (typeof unset == "function")
|
|
881
872
|
unset(value2);
|
|
882
873
|
unset = (next) => {
|
|
883
|
-
if (typeof
|
|
884
|
-
|
|
874
|
+
if (typeof returns == "function")
|
|
875
|
+
returns(next);
|
|
885
876
|
flush();
|
|
886
877
|
};
|
|
887
878
|
};
|
|
@@ -922,27 +913,31 @@ function has(arg1, arg2) {
|
|
|
922
913
|
if (Model.is(arg1))
|
|
923
914
|
Context.get(subject, (ctx) => {
|
|
924
915
|
ctx.has(arg1, (model) => {
|
|
925
|
-
const ctx2 = context();
|
|
926
916
|
let remove;
|
|
927
917
|
let disconnect;
|
|
918
|
+
let flush;
|
|
928
919
|
if (applied.has(model))
|
|
929
920
|
return;
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
const
|
|
933
|
-
if (
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
if (
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
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();
|
|
944
940
|
}
|
|
945
|
-
const flush = ctx2();
|
|
946
941
|
applied.add(model);
|
|
947
942
|
reset();
|
|
948
943
|
const done = () => {
|
|
@@ -956,7 +951,7 @@ function has(arg1, arg2) {
|
|
|
956
951
|
remove();
|
|
957
952
|
remove = void 0;
|
|
958
953
|
};
|
|
959
|
-
const ignore = model.set(
|
|
954
|
+
const ignore = model.set(done, null);
|
|
960
955
|
return done;
|
|
961
956
|
});
|
|
962
957
|
});
|
|
@@ -988,9 +983,10 @@ function has(arg1, arg2) {
|
|
|
988
983
|
Context,
|
|
989
984
|
METHOD,
|
|
990
985
|
Model,
|
|
986
|
+
Observable,
|
|
991
987
|
addListener,
|
|
992
988
|
createEffect,
|
|
993
|
-
|
|
989
|
+
event,
|
|
994
990
|
get,
|
|
995
991
|
has,
|
|
996
992
|
ref,
|