@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/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,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 null;
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
- return reset;
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 ctx = context(argument === false);
166
- const ret = callback.call(subscriber, subscriber);
167
- const flush = ctx();
168
- reset = ret === null ? null : invoke;
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 ret == "function")
171
- ret(key2);
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 context(ignore) {
167
+ function enter(ignore) {
202
168
  if (ignore)
203
169
  return () => () => {
204
170
  };
205
- const current = EffectContext;
206
- const ctx = EffectContext = /* @__PURE__ */ new Set();
171
+ const last = EffectContext;
172
+ const context = EffectContext = /* @__PURE__ */ new Set();
207
173
  return () => {
208
- EffectContext = current;
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 pending2 = /* @__PURE__ */ new Set();
210
+ let pending = /* @__PURE__ */ new Set();
233
211
  return createEffect(self, (proxy) => {
234
- const cb = arg1.call(proxy, proxy, pending2);
212
+ const cb = arg1.call(proxy, proxy, pending);
235
213
  return cb === null ? null : (update2) => {
236
- pending2 = PENDING_KEYS.get(self);
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
- return pending(self);
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 === true);
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
- 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
- }
366
+ if ("value" in desc)
367
+ manage(model, key2, desc.value, true);
396
368
  }
397
- args.forEach((arg) => {
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 = child(arg1, arg2);
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 child(type, arg2) {
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, (context2) => {
716
- const model = context2.get(arg0);
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 ctx = context();
810
+ const exit = enter();
819
811
  const out = arg.call(subject, value2);
820
- const flush = ctx();
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 ctx = context();
876
- const out = argument.call(this, value2, previous);
877
- const flush = ctx();
878
- if (out === false)
879
- return out;
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 out == "function")
884
- out(next);
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 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;
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(null, done);
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
- createProxy,
990
+ event,
994
991
  get,
995
992
  has,
996
993
  ref,