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