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

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.esm.js CHANGED
@@ -20,7 +20,7 @@ function issues(register) {
20
20
  return Library;
21
21
  }
22
22
 
23
- const Oops$8 = issues({
23
+ const Oops$9 = issues({
24
24
  BadEffectCallback: () => `Callback for effect-callback may only return a function.`
25
25
  });
26
26
  const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys: keys$1, values } = Object;
@@ -49,7 +49,7 @@ function createEffect(callback) {
49
49
  if (unSet instanceof Promise)
50
50
  unSet = undefined;
51
51
  if (unSet && typeof unSet !== "function")
52
- throw Oops$8.BadEffectCallback();
52
+ throw Oops$9.BadEffectCallback();
53
53
  };
54
54
  }
55
55
  function createValueEffect(callback) {
@@ -65,7 +65,7 @@ function createValueEffect(callback) {
65
65
  if (typeof out == "function")
66
66
  unSet = out;
67
67
  else
68
- throw Oops$8.BadEffectCallback();
68
+ throw Oops$9.BadEffectCallback();
69
69
  };
70
70
  }
71
71
  function select(source, select) {
@@ -94,6 +94,13 @@ class Subscriber {
94
94
  this.active = false;
95
95
  this.handle = {};
96
96
  this.dependant = new Set();
97
+ this.debug = () => {
98
+ const update = [];
99
+ this.notify = keys => {
100
+ update.splice(0, update.length, ...keys.filter(k => k in this.handle));
101
+ };
102
+ return update;
103
+ };
97
104
  this.listen = (key, from) => {
98
105
  const handler = this.handle[key];
99
106
  if (!handler)
@@ -103,28 +110,16 @@ class Subscriber {
103
110
  const notify = this.onUpdate(key, from);
104
111
  if (notify)
105
112
  from.waiting.add(notify);
113
+ if (this.notify)
114
+ from.waiting.add(this.notify);
106
115
  };
107
116
  if (!(parent instanceof Controller))
108
117
  parent = manage(parent);
109
- const subject = this.source =
110
- parent.subject;
111
- const proxy = this.proxy =
112
- create(subject);
113
118
  this.parent = parent;
119
+ this.source = parent.subject;
120
+ this.proxy = create(parent.subject);
114
121
  define(this.proxy, LOCAL, this);
115
- defineProperty(this.proxy, UPDATE, {
116
- get: () => (this.parent.handled.filter(key => key in this.handle))
117
- });
118
- if ("update" in subject) {
119
- define(proxy, "update", (...args) => {
120
- if (!args.length) {
121
- const refresh = this.onUpdate("", parent);
122
- if (refresh)
123
- refresh([]);
124
- }
125
- return subject.update(...args);
126
- });
127
- }
122
+ defineLazy(this.proxy, UPDATE, this.debug);
128
123
  for (const key in parent.state)
129
124
  this.spy(key);
130
125
  }
@@ -158,7 +153,7 @@ class Subscriber {
158
153
  }
159
154
  }
160
155
 
161
- const Oops$7 = issues({
156
+ const Oops$8 = issues({
162
157
  ComputeFailed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
163
158
  ComputedEarly: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
164
159
  });
@@ -177,14 +172,14 @@ function prepare(parent, key, source, setter, getter) {
177
172
  }
178
173
  register.set(key, info);
179
174
  const current = getter
180
- ? () => getter.call(subject, state[key], key)
175
+ ? () => getter(parent, key)
181
176
  : () => state[key];
182
177
  function compute(initial) {
183
178
  try {
184
179
  return setter.call(sub.proxy, sub.proxy);
185
180
  }
186
181
  catch (err) {
187
- Oops$7.ComputeFailed(subject, key, !!initial).warn();
182
+ Oops$8.ComputeFailed(subject, key, !!initial).warn();
188
183
  throw err;
189
184
  }
190
185
  }
@@ -230,7 +225,7 @@ function prepare(parent, key, source, setter, getter) {
230
225
  }
231
226
  catch (e) {
232
227
  if (early)
233
- Oops$7.ComputedEarly(key).warn();
228
+ Oops$8.ComputedEarly(key).warn();
234
229
  throw e;
235
230
  }
236
231
  finally {
@@ -356,30 +351,16 @@ class Controller {
356
351
  this.state = {};
357
352
  this.frame = new Set();
358
353
  this.waiting = new Set();
359
- this.handled = [];
360
354
  this.followers = new Set();
361
355
  }
362
356
  static setup(onto) {
363
357
  const control = new this(onto);
364
- defineProperty(onto, CONTROL, {
365
- configurable: true,
366
- get() {
367
- defineProperty(onto, CONTROL, {
368
- value: control
369
- });
370
- defineProperty(onto, STATE, {
371
- get: () => (Object.assign({}, control.state)),
372
- configurable: true
373
- });
374
- defineProperty(onto, UPDATE, {
375
- get: () => [...control.handled],
376
- configurable: true
377
- });
378
- control.start();
379
- if (onto.didCreate)
380
- onto.didCreate();
381
- return control;
382
- }
358
+ defineLazy(onto, CONTROL, () => {
359
+ onto[STATE] = control.state;
360
+ control.start();
361
+ if (onto.didCreate)
362
+ onto.didCreate();
363
+ return control;
383
364
  });
384
365
  return control;
385
366
  }
@@ -458,14 +439,17 @@ class Controller {
458
439
  }
459
440
  emit() {
460
441
  flush(this);
442
+ const keys = Object.freeze([...this.frame]);
461
443
  const handle = new Set(this.waiting);
462
- const handled = this.handled =
463
- Object.freeze([...this.frame]);
464
444
  this.waiting.clear();
465
445
  this.frame.clear();
446
+ defineProperty(this.subject, UPDATE, {
447
+ configurable: true,
448
+ value: keys
449
+ });
466
450
  handle.forEach(callback => {
467
451
  try {
468
- callback(handled);
452
+ callback(keys);
469
453
  }
470
454
  catch (e) { }
471
455
  });
@@ -522,6 +506,61 @@ function child(source, name) {
522
506
  }, name || source.name);
523
507
  }
524
508
 
509
+ const Oops$7 = issues({
510
+ NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
511
+ BadFactory: () => `Set instruction can only accept a factory or undefined.`,
512
+ FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
513
+ });
514
+ function lazy(value) {
515
+ return apply(function lazy(key) {
516
+ const source = this.subject;
517
+ source[key] = value;
518
+ defineProperty(this.state, key, {
519
+ get: () => source[key]
520
+ });
521
+ });
522
+ }
523
+ function set(factory, argument) {
524
+ return apply(function set(key) {
525
+ let onSet;
526
+ let onGet;
527
+ const required = argument === true || argument === undefined;
528
+ if (factory === undefined)
529
+ onGet = () => pendingValue(this, key);
530
+ else if (typeof factory !== "function")
531
+ throw Oops$7.BadFactory();
532
+ else {
533
+ onGet = pendingFactory(this, key, factory);
534
+ if (required)
535
+ try {
536
+ onGet();
537
+ }
538
+ catch (err) {
539
+ if (err instanceof Promise)
540
+ ;
541
+ else {
542
+ Oops$7.FactoryFailed(this.subject, key).warn();
543
+ throw err;
544
+ }
545
+ }
546
+ }
547
+ if (typeof argument == "function")
548
+ onSet = createValueEffect(argument);
549
+ else if (required)
550
+ onSet = (value) => {
551
+ if (value === undefined)
552
+ throw Oops$7.NonOptional(this.subject, key);
553
+ };
554
+ return {
555
+ set: this.setter(key, onSet),
556
+ get: onGet
557
+ };
558
+ });
559
+ }
560
+ function on(initial, onUpdate) {
561
+ return set(initial && (() => initial), onUpdate);
562
+ }
563
+
525
564
  const Oops$6 = issues({
526
565
  CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
527
566
  AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
@@ -624,10 +663,13 @@ function act(task) {
624
663
  };
625
664
  });
626
665
  }
627
- function from(source, setter, getter) {
666
+ function from(source, setter, argument) {
628
667
  return apply(function from(key) {
629
668
  const { subject } = this;
630
669
  let getSource;
670
+ let getter = argument === true
671
+ ? pendingValue
672
+ : argument || undefined;
631
673
  // Easy mistake, using a peer, will always be unresolved.
632
674
  if (typeof source == "symbol")
633
675
  throw Oops$5.PeerNotAllowed(subject, key);
@@ -642,7 +684,7 @@ function from(source, setter, getter) {
642
684
  // is a peer Model (constructor)
643
685
  else if (Model.isTypeof(source))
644
686
  getSource = pendingAccess(subject, source, key, true);
645
- // Regular function is to ambiguous so not allowed.
687
+ // Regular function is too ambiguous so not allowed.
646
688
  else
647
689
  throw Oops$5.BadComputedSource(subject, key, source);
648
690
  prepare(this, key, getSource, setter, getter);
@@ -652,12 +694,14 @@ function from(source, setter, getter) {
652
694
  const Oops$4 = issues({
653
695
  ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
654
696
  });
697
+ /* deprecated - ignore coverage */
698
+ /* istanbul ignore next */
655
699
  function pending(source, compute) {
656
- return (source === undefined ?
657
- suspendForValue() :
658
- typeof source == "function" && !source.prototype ?
659
- suspendForAsync(source) :
660
- suspendForComputed(source, compute));
700
+ if (source === undefined)
701
+ return set();
702
+ if (typeof source == "function" && !source.prototype)
703
+ return set(source);
704
+ return from(source, compute, true);
661
705
  }
662
706
  /**
663
707
  * Get value, suspend instead if undefined.
@@ -671,6 +715,40 @@ function pendingValue(via, key) {
671
715
  throw suspend(via, key);
672
716
  return value;
673
717
  }
718
+ function pendingFactory(via, key, fn) {
719
+ const { subject, state } = via;
720
+ let waiting;
721
+ let error;
722
+ return () => {
723
+ if (waiting)
724
+ throw waiting;
725
+ if (error)
726
+ throw error;
727
+ if (key in state)
728
+ return state[key];
729
+ let output;
730
+ try {
731
+ output = fn.call(subject, key, subject);
732
+ }
733
+ catch (err) {
734
+ throw error = err;
735
+ }
736
+ if (output instanceof Promise) {
737
+ const issue = Oops$4.ValueNotReady(subject, key);
738
+ output
739
+ .catch(err => error = err)
740
+ .then(out => state[key] = out)
741
+ .finally(() => waiting = undefined);
742
+ throw waiting = Object.assign(output, {
743
+ message: issue.message,
744
+ stack: issue.stack
745
+ });
746
+ }
747
+ else {
748
+ return state[key] = output;
749
+ }
750
+ };
751
+ }
674
752
  function suspend(source, key) {
675
753
  const error = Oops$4.ValueNotReady(source.subject, key);
676
754
  const promise = new Promise(resolve => {
@@ -690,45 +768,6 @@ function suspend(source, key) {
690
768
  message: error.message,
691
769
  stack: error.stack
692
770
  });
693
- }
694
- function suspendForComputed(source, compute) {
695
- function getter(_value, key) {
696
- return pendingValue(manage(this), key);
697
- }
698
- return from(source, compute, getter);
699
- }
700
- function suspendForValue() {
701
- return apply(function pending(key) {
702
- this.state[key] = undefined;
703
- return {
704
- set: this.setter(key),
705
- get: () => pendingValue(this, key)
706
- };
707
- });
708
- }
709
- function suspendForAsync(source) {
710
- return apply(function suspense(key) {
711
- const subject = this.subject;
712
- let waiting = true;
713
- let value;
714
- let error;
715
- return () => {
716
- if (error)
717
- throw error;
718
- if (!waiting)
719
- return value;
720
- const issue = Oops$4.ValueNotReady(subject, key);
721
- let suspend = source
722
- .call(subject, key)
723
- .catch(err => error = err)
724
- .then(out => value = out)
725
- .finally(() => waiting = false);
726
- throw Object.assign(suspend, {
727
- message: issue.message,
728
- stack: issue.stack
729
- });
730
- };
731
- });
732
771
  }
733
772
 
734
773
  function use$1(init) {
@@ -969,9 +1008,7 @@ class Model {
969
1008
  return proxy;
970
1009
  }
971
1010
  tag(id) {
972
- const hook = use$1(refresh => {
973
- return new Subscriber(this, () => refresh);
974
- });
1011
+ const hook = use$1(refresh => (new Subscriber(this, () => refresh)));
975
1012
  useElementLifecycle(hook, id || 0);
976
1013
  return hook.proxy;
977
1014
  }
@@ -1019,12 +1056,10 @@ class Model {
1019
1056
  invoke();
1020
1057
  return this.on(select, invoke, true);
1021
1058
  }
1022
- else {
1023
- const sub = new Subscriber(control, () => invoke);
1024
- target = sub.proxy;
1025
- invoke();
1026
- return sub.commit();
1027
- }
1059
+ const sub = new Subscriber(control, () => invoke);
1060
+ target = sub.proxy;
1061
+ invoke();
1062
+ return sub.commit();
1028
1063
  }
1029
1064
  import(from, subset) {
1030
1065
  for (const key of keys(manage(this), subset))
@@ -1220,31 +1255,6 @@ function parent(Expects, required) {
1220
1255
  });
1221
1256
  }
1222
1257
 
1223
- function on(initial, cb) {
1224
- return apply(function on(key) {
1225
- this.manage(key, initial, cb && createValueEffect(cb));
1226
- });
1227
- }
1228
- function memo(factory, defer) {
1229
- return apply(function memo(key) {
1230
- const source = this.subject;
1231
- const get = () => factory.call(source);
1232
- if (defer)
1233
- defineLazy(source, key, get);
1234
- else
1235
- define(source, key, get());
1236
- });
1237
- }
1238
- function lazy(value) {
1239
- return apply(function lazy(key) {
1240
- const source = this.subject;
1241
- source[key] = value;
1242
- defineProperty(this.state, key, {
1243
- get: () => source[key]
1244
- });
1245
- });
1246
- }
1247
-
1248
1258
  const Oops = issues({
1249
1259
  GlobalDoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.create() before attempting to access, or consider using ${name}.use() instead.`,
1250
1260
  GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
@@ -1286,5 +1296,5 @@ class Singleton extends Model {
1286
1296
  }
1287
1297
  }
1288
1298
 
1289
- export { Consumer, Model, Provider, Singleton, act, apply, child, Model as default, from, lazy, memo, on, parent, pending, ref, tap, use };
1299
+ export { Consumer, Model, Provider, Singleton, act, apply, child, Model as default, from, lazy, set as memo, on, parent, pending, ref, set, tap, use };
1290
1300
  //# sourceMappingURL=index.esm.js.map