@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/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
- const filter = select === void 0 ? void 0 : /* @__PURE__ */ new Set([select]);
50
- if (!listeners.has(onReady) && !filter)
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, filter);
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 pending2 = PENDING.get(model);
61
- if (pending2) {
62
- pending2.add(key2);
62
+ let pending = PENDING.get(model);
63
+ if (pending) {
64
+ pending.add(key2);
63
65
  return;
64
66
  }
65
- PENDING.set(model, pending2 = new Set(notReady ? [true, key2] : [key2]));
66
- for (const key3 of pending2)
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 pending2 = PENDING_KEYS.get(subject);
85
- if (!pending2) {
86
- PENDING_KEYS.set(subject, pending2 = /* @__PURE__ */ new Set());
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
- pending2.add(key2);
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
- 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(
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 ctx = context(argument === false);
169
- const ret = callback.call(subscriber, subscriber);
170
- const flush = ctx();
171
- reset = ret === null ? null : invoke;
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 ret == "function")
174
- ret(key2);
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 context(ignore) {
166
+ function enter(ignore) {
205
167
  if (ignore)
206
168
  return () => () => {
207
169
  };
208
- const current = EffectContext;
209
- const ctx = EffectContext = /* @__PURE__ */ new Set();
170
+ const last = EffectContext;
171
+ const context = EffectContext = /* @__PURE__ */ new Set();
210
172
  return () => {
211
- EffectContext = current;
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 pending2 = /* @__PURE__ */ new Set();
209
+ let pending = /* @__PURE__ */ new Set();
236
210
  return createEffect(self, (proxy) => {
237
- const cb = arg1.call(proxy, proxy, pending2);
211
+ const cb = arg1.call(proxy, proxy, pending);
238
212
  return cb === null ? null : (update2) => {
239
- pending2 = PENDING_KEYS.get(self);
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
- return pending(self);
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 === true);
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
- let set3 = function(value, silent) {
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
- args.forEach((arg) => {
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 = child(arg1, arg2);
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 child(type, arg2) {
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, (context2) => {
719
- const model = context2.get(arg0);
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 ctx = context();
809
+ const exit = enter();
822
810
  const out = arg.call(subject, value2);
823
- const flush = ctx();
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
- (value2) => update(subject, key2, value2),
857
- (error) => {
858
- event(subject, key2);
859
- property.get = () => {
860
- throw error;
861
- };
862
- }
863
- );
844
+ value.then(set2, (error) => {
845
+ event(subject, key2);
846
+ property.get = () => {
847
+ throw error;
848
+ };
849
+ });
864
850
  else
865
- update(subject, key2, value);
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 ctx = context();
881
- const out = argument.call(this, value2, previous);
882
- const flush = ctx();
883
- if (out === false)
884
- return out;
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 out == "function")
889
- out(next);
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 notify = APPLY.get(model);
936
- if (notify) {
937
- const after = notify(subject);
938
- if (after === false)
939
- return;
940
- if (typeof after == "function")
941
- disconnect = after;
942
- }
943
- if (typeof arg2 == "function") {
944
- const done2 = arg2(model, subject);
945
- if (done2 === false)
946
- return false;
947
- if (typeof done2 == "function")
948
- remove = done2;
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(null, done);
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
- createProxy,
989
+ event,
999
990
  get,
1000
991
  has,
1001
992
  ref,