@expressive/mvc 1.0.0-beta.33 → 1.0.0-beta.34

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/lib/index.js CHANGED
@@ -96,58 +96,51 @@ class Subscriber {
96
96
  constructor(parent, onUpdate) {
97
97
  this.onUpdate = onUpdate;
98
98
  this.active = false;
99
- this.handle = {};
99
+ this.using = {};
100
100
  this.dependant = new Set();
101
- this.debug = () => {
102
- const update = [];
103
- this.notify = keys => {
104
- update.splice(0, update.length, ...keys.filter(k => k in this.handle));
105
- };
106
- return update;
107
- };
108
- this.listen = (key, from) => {
109
- const handler = this.handle[key];
110
- if (!handler)
111
- return;
112
- if (typeof handler == "function")
113
- handler();
114
- const notify = this.onUpdate(key, from);
115
- if (notify)
116
- from.waiting.add(notify);
117
- if (this.notify)
118
- from.waiting.add(this.notify);
119
- };
120
101
  if (!(parent instanceof Controller))
121
102
  parent = manage(parent);
122
103
  this.parent = parent;
123
104
  this.source = parent.subject;
124
105
  this.proxy = create(parent.subject);
125
106
  define(this.proxy, LOCAL, this);
126
- defineLazy(this.proxy, UPDATE, this.debug);
107
+ defineLazy(this.proxy, UPDATE, () => {
108
+ const update = [];
109
+ this.notify = keys => {
110
+ update.splice(0, update.length, ...keys.filter(k => k in this.using));
111
+ };
112
+ return update;
113
+ });
127
114
  for (const key in parent.state)
128
115
  this.spy(key);
129
116
  }
130
117
  spy(key) {
131
- const { proxy, source } = this;
132
- const { set } = getOwnPropertyDescriptor(source, key);
133
- const intercept = () => {
134
- this.follow(key);
118
+ const { proxy } = this;
119
+ const existing = getOwnPropertyDescriptor(this.source, key);
120
+ const isUsing = () => {
121
+ this.using[key] = true;
135
122
  delete proxy[key];
136
123
  return proxy[key];
137
124
  };
138
- setAlias(intercept, `tap ${key}`);
125
+ setAlias(isUsing, `tap ${key}`);
139
126
  defineProperty(proxy, key, {
140
- get: intercept,
141
- set,
127
+ set: existing.set,
128
+ get: isUsing,
142
129
  configurable: true,
143
130
  enumerable: true
144
131
  });
145
132
  }
146
- follow(key, callback) {
147
- this.handle[key] = callback || true;
148
- }
149
133
  commit() {
150
- const onDone = this.parent.addListener(this.listen);
134
+ const onDone = this.parent.addListener((key, source) => {
135
+ const handler = this.using[key];
136
+ if (!handler)
137
+ return;
138
+ if (typeof handler == "function")
139
+ handler();
140
+ const notify = this.onUpdate(key, source);
141
+ source.onUpdate(notify);
142
+ source.onUpdate(this.notify);
143
+ });
151
144
  this.active = true;
152
145
  this.dependant.forEach(x => x.commit());
153
146
  return this.release = () => {
@@ -234,7 +227,7 @@ function prepare(parent, key, source, setter, getter) {
234
227
  }
235
228
  finally {
236
229
  sub.commit();
237
- for (const key in sub.handle) {
230
+ for (const key in sub.using) {
238
231
  const peer = register.get(key);
239
232
  if (peer && peer.priority >= info.priority)
240
233
  info.priority = peer.priority + 1;
@@ -371,6 +364,10 @@ class Controller {
371
364
  get pending() {
372
365
  return this.frame.size > 0;
373
366
  }
367
+ onUpdate(cb) {
368
+ if (typeof cb == "function")
369
+ this.waiting.add(cb);
370
+ }
374
371
  start() {
375
372
  const { subject } = this;
376
373
  for (const key in subject) {
@@ -435,11 +432,8 @@ class Controller {
435
432
  if (!this.frame.size)
436
433
  setTimeout(() => this.emit(), 0);
437
434
  this.frame.add(key);
438
- for (const subscription of this.followers) {
439
- const notify = subscription(key, this);
440
- if (notify)
441
- this.waiting.add(notify);
442
- }
435
+ for (const callback of this.followers)
436
+ this.onUpdate(callback(key, this));
443
437
  }
444
438
  emit() {
445
439
  flush(this);
@@ -498,7 +492,7 @@ function child(source, name) {
498
492
  start();
499
493
  }
500
494
  start();
501
- sub.follow(key, restart);
495
+ sub.using[key] = restart;
502
496
  }
503
497
  return (local) => {
504
498
  if (!local)
@@ -669,9 +663,9 @@ function act(task) {
669
663
  }
670
664
  function from(source, setter, argument) {
671
665
  return apply(function from(key) {
672
- const { subject } = this;
673
666
  let getSource;
674
- let getter = argument === true
667
+ const { subject } = this;
668
+ const getter = argument === true
675
669
  ? pendingValue
676
670
  : argument || undefined;
677
671
  // Easy mistake, using a peer, will always be unresolved.
@@ -812,13 +806,11 @@ function useWatcher(target, focus, expected) {
812
806
  function useComputed(target, compute, expected) {
813
807
  const hook = use$1(refresh => {
814
808
  const sub = new Subscriber(target, () => update);
815
- const { proxy } = sub;
816
- let value;
809
+ const spy = sub.proxy;
810
+ let value = compute.call(spy, spy);
811
+ let update;
817
812
  let retry;
818
- const update = () => {
819
- const next = compute.call(proxy, proxy);
820
- if (value == next)
821
- return;
813
+ const set = (next) => {
822
814
  value = next;
823
815
  if (retry) {
824
816
  retry();
@@ -827,16 +819,26 @@ function useComputed(target, compute, expected) {
827
819
  else
828
820
  refresh();
829
821
  };
830
- const access = () => {
831
- if (value === undefined && expected)
832
- throw new Promise(res => {
833
- retry = res;
834
- });
835
- return value;
836
- };
837
- value = compute.call(proxy, proxy);
838
- sub.commit();
839
- defineProperty(sub, "proxy", { get: access });
822
+ if (value instanceof Promise) {
823
+ value.then(set);
824
+ value = undefined;
825
+ }
826
+ else {
827
+ sub.commit();
828
+ update = () => {
829
+ const next = compute.call(spy, spy);
830
+ if (value != next)
831
+ set(next);
832
+ };
833
+ }
834
+ const get = expected
835
+ ? () => {
836
+ if (value === undefined)
837
+ throw new Promise(res => retry = res);
838
+ return value;
839
+ }
840
+ : () => value;
841
+ defineProperty(sub, "proxy", { get });
840
842
  return sub;
841
843
  });
842
844
  react.useLayoutEffect(() => hook.release, []);
@@ -999,7 +1001,7 @@ class Model {
999
1001
  define(this, "set", this);
1000
1002
  defer(control, "on");
1001
1003
  defer(control, "effect");
1002
- control.waiting.add(() => {
1004
+ control.onUpdate(() => {
1003
1005
  delete this.on;
1004
1006
  delete this.effect;
1005
1007
  });
@@ -1046,10 +1048,9 @@ class Model {
1046
1048
  once(select, callback, squash) {
1047
1049
  if (callback)
1048
1050
  return this.on(select, callback, squash, true);
1049
- else
1050
- return new Promise(resolve => {
1051
- this.on(select, resolve, true, true);
1052
- });
1051
+ return new Promise(resolve => {
1052
+ this.on(select, resolve, true, true);
1053
+ });
1053
1054
  }
1054
1055
  effect(callback, select) {
1055
1056
  const control = manage(this);