@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/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,27 +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(value = createProxy(value, access), nested);
162
- return value;
163
- }
128
+ const subscriber = target[Observable](onUpdate, argument === true);
164
129
  try {
165
- const ctx = context(argument === false);
166
- const ret = callback.call(subscriber, subscriber);
167
- const flush = ctx();
168
- 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;
169
134
  unset = (key2) => {
170
- if (typeof ret == "function")
171
- ret(key2);
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 context(ignore) {
166
+ function enter(ignore) {
202
167
  if (ignore)
203
168
  return () => () => {
204
169
  };
205
- const current = EffectContext;
206
- const ctx = EffectContext = /* @__PURE__ */ new Set();
170
+ const last = EffectContext;
171
+ const context = EffectContext = /* @__PURE__ */ new Set();
207
172
  return () => {
208
- EffectContext = current;
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 pending2 = /* @__PURE__ */ new Set();
209
+ let pending = /* @__PURE__ */ new Set();
233
210
  return createEffect(self, (proxy) => {
234
- const cb = arg1.call(proxy, proxy, pending2);
211
+ const cb = arg1.call(proxy, proxy, pending);
235
212
  return cb === null ? null : (update2) => {
236
- pending2 = PENDING_KEYS.get(self);
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
- 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
+ };
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 === true);
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
- let set3 = function(value, silent) {
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
- args.forEach((arg) => {
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 = child(arg1, arg2);
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 child(type, arg2) {
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, (context2) => {
716
- const model = context2.get(arg0);
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 ctx = context();
809
+ const exit = enter();
819
810
  const out = arg.call(subject, value2);
820
- const flush = ctx();
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 ctx = context();
876
- const out = argument.call(this, value2, previous);
877
- const flush = ctx();
878
- if (out === false)
879
- 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;
880
871
  if (typeof unset == "function")
881
872
  unset(value2);
882
873
  unset = (next) => {
883
- if (typeof out == "function")
884
- out(next);
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 notify = APPLY.get(model);
931
- if (notify) {
932
- const after = notify(subject);
933
- if (after === false)
934
- return;
935
- if (typeof after == "function")
936
- disconnect = after;
937
- }
938
- if (typeof arg2 == "function") {
939
- const done2 = arg2(model, subject);
940
- if (done2 === false)
941
- return false;
942
- if (typeof done2 == "function")
943
- 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();
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(null, done);
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
- createProxy,
989
+ event,
994
990
  get,
995
991
  has,
996
992
  ref,