@expressive/mvc 0.15.2 → 0.17.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/lib/index.js CHANGED
@@ -8,6 +8,23 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
8
8
 
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
 
11
+ class Issue extends Error {
12
+ constructor() {
13
+ super(...arguments);
14
+ // drop first line (error factory) in stack trace.
15
+ this.stack = this.stack.replace(/\n.+/, "");
16
+ }
17
+ warn() {
18
+ console.warn(this.message);
19
+ }
20
+ }
21
+ function issues(register) {
22
+ const Library = {};
23
+ for (const name in register)
24
+ Library[name] = (...args) => new Issue(register[name].apply(null, args));
25
+ return Library;
26
+ }
27
+
11
28
  const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
12
29
  const UID_CACHE = new WeakMap();
13
30
  function assignWeak(into, from) {
@@ -22,28 +39,82 @@ function uid(object) {
22
39
  return uid;
23
40
  }
24
41
 
25
- class Issue extends Error {
26
- constructor() {
27
- super(...arguments);
28
- // drop first line (error factory) in stack trace.
29
- this.stack = this.stack.replace(/\n.+/, "");
42
+ const REGISTER$1 = new WeakMap();
43
+ class Subscriber {
44
+ constructor(parent, onUpdate, strict) {
45
+ this.parent = parent;
46
+ this.onUpdate = onUpdate;
47
+ this.strict = strict;
48
+ this.active = false;
49
+ this.dependant = new Set();
50
+ this.watch = new Map();
51
+ const proxy = create(parent.subject);
52
+ const reset = () => this.latest = undefined;
53
+ REGISTER$1.set(proxy, this);
54
+ defineProperty(this, "proxy", {
55
+ configurable: true,
56
+ get() {
57
+ setTimeout(reset, 0);
58
+ return proxy;
59
+ }
60
+ });
61
+ this.clear = parent.addListener(key => {
62
+ if (this.active)
63
+ this.notify(key);
64
+ });
30
65
  }
31
- warn() {
32
- console.warn(this.message);
66
+ get using() {
67
+ return Array.from(this.watch.keys());
68
+ }
69
+ apply(values, keys) {
70
+ const { waiting, subject } = this.parent;
71
+ this.active = false;
72
+ if (!keys)
73
+ keys = getOwnPropertyNames(subject);
74
+ for (const key of keys)
75
+ if (key in values)
76
+ subject[key] = values[key];
77
+ waiting.add(() => this.active = true);
78
+ }
79
+ follow(key, value) {
80
+ if (value !== undefined)
81
+ this.watch.set(key, value);
82
+ else if (!this.watch.has(key))
83
+ this.watch.set(key, true);
84
+ }
85
+ commit() {
86
+ this.active = true;
87
+ this.dependant.forEach(x => x.commit());
88
+ }
89
+ release() {
90
+ this.clear();
91
+ this.dependant.forEach(x => x.release());
92
+ }
93
+ notify(key) {
94
+ const { parent, watch } = this;
95
+ const handler = watch.get(key);
96
+ if (!handler)
97
+ return;
98
+ if (typeof handler == "function")
99
+ handler();
100
+ const notify = this.onUpdate(key, parent);
101
+ if (notify) {
102
+ parent.waiting.add(update => {
103
+ this.latest = update.filter(k => watch.has(k));
104
+ });
105
+ parent.waiting.add(notify);
106
+ }
33
107
  }
34
108
  }
35
- function issues(register) {
36
- const Library = {};
37
- for (const name in register)
38
- Library[name] = (...args) => new Issue(register[name].apply(null, args));
39
- return Library;
109
+ function subscriber(from) {
110
+ return REGISTER$1.get(from);
40
111
  }
41
112
 
42
- const Oops$f = issues({
113
+ const Oops$c = issues({
43
114
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
44
115
  });
45
116
  function suspend(source, key) {
46
- const error = Oops$f.NotReady(source.subject, key);
117
+ const error = Oops$c.NotReady(source.subject, key);
47
118
  const promise = new Promise(resolve => {
48
119
  const release = source.addListener(forKey => {
49
120
  if (forKey == key)
@@ -83,98 +154,87 @@ function mayRetry(fn) {
83
154
  return compute();
84
155
  }
85
156
 
86
- const Oops$e = issues({
87
- Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
157
+ const Parent = new WeakMap();
158
+ const Oops$b = issues({
159
+ BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
160
+ Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
161
+ Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
88
162
  });
89
- const INFO = new WeakMap();
90
- const KEYS = new WeakMap();
91
- const ORDER = new WeakMap();
92
- function computeMode(self, source, setter, key, required) {
93
- const { subject, state } = self;
94
- let sub;
95
- let order = ORDER.get(self);
96
- let pending = KEYS.get(self);
97
- if (!order)
98
- ORDER.set(self, order = new Map());
99
- if (!pending)
100
- KEYS.set(self, pending = new Set());
101
- const compute = (initial) => {
102
- try {
103
- return setter.call(sub.proxy, sub.proxy);
104
- }
105
- catch (err) {
106
- Oops$e.Failed(subject, key, initial).warn();
107
- throw err;
108
- }
163
+ function getParentForGetInstruction(type, relativeTo, required) {
164
+ const item = getParent(type, relativeTo);
165
+ return (_refresh) => {
166
+ if (item)
167
+ return item;
168
+ if (required)
169
+ throw Oops$b.Required(type.name, relativeTo);
109
170
  };
110
- const refresh = () => {
111
- let value;
112
- try {
113
- value = compute(false);
114
- }
115
- catch (e) {
116
- console.error(e);
117
- }
118
- finally {
119
- if (state.get(key) !== value) {
120
- state.set(key, value);
121
- self.update(key);
122
- return value;
123
- }
171
+ }
172
+ function getParent(type, from) {
173
+ const value = Parent.get(from);
174
+ if (value && !(value instanceof type))
175
+ throw Oops$b.Unexpected(type.name, from, value);
176
+ return value;
177
+ }
178
+ function getRecursive(key, from) {
179
+ const context = new WeakMap();
180
+ const { state } = from;
181
+ return (local) => {
182
+ if (!state.has(key))
183
+ throw suspend(from, key);
184
+ if (!local)
185
+ return state.get(key);
186
+ if (!context.has(local)) {
187
+ let reset;
188
+ const init = () => {
189
+ if (reset)
190
+ reset();
191
+ const value = state.get(key);
192
+ if (value && controller(value)) {
193
+ const child = new Subscriber(control(value), local.onUpdate);
194
+ if (local.active)
195
+ child.commit();
196
+ local.dependant.add(child);
197
+ context.set(local, child.proxy);
198
+ reset = () => {
199
+ child.release();
200
+ local.dependant.delete(child);
201
+ context.set(local, undefined);
202
+ reset = undefined;
203
+ };
204
+ }
205
+ };
206
+ local.follow(key, init);
207
+ init();
124
208
  }
209
+ return context.get(local);
125
210
  };
126
- const create = () => {
127
- sub = source.subscribe((_, source) => {
128
- if (source !== self)
129
- refresh();
130
- else
131
- pending.add(refresh);
132
- });
133
- sub.watch.set(key, false);
134
- try {
135
- const value = compute(true);
136
- state.set(key, value);
137
- return value;
138
- }
139
- catch (e) {
140
- throw e;
141
- }
142
- finally {
143
- sub.commit();
144
- order.set(refresh, order.size);
145
- }
211
+ }
212
+ function setRecursive(controller, key, initial) {
213
+ const { state, subject } = controller;
214
+ const Type = initial.constructor;
215
+ let get;
216
+ const onUpdate = (next) => {
217
+ state.set(key, next);
218
+ if (!(next instanceof Type))
219
+ throw Oops$b.BadAssignment(`${subject}.${key}`, Type.name, String(next));
220
+ get = getRecursive(key, controller);
221
+ Parent.set(next, subject);
222
+ control(next);
223
+ return true;
146
224
  };
147
- INFO.set(refresh, key);
148
- return () => {
149
- if (pending.has(refresh)) {
150
- pending.delete(refresh);
151
- refresh();
225
+ onUpdate(initial);
226
+ defineProperty(subject, key, {
227
+ set: controller.ref(key, onUpdate),
228
+ get() {
229
+ const local = subscriber(this);
230
+ if (local)
231
+ local.follow(key);
232
+ return get(local);
152
233
  }
153
- const value = sub ? state.get(key) : create();
154
- if (value === undefined && required)
155
- throw suspend(self, key);
156
- return value;
157
- };
158
- }
159
- function flush(control) {
160
- const pending = KEYS.get(control);
161
- if (!pending || !pending.size)
162
- return;
163
- const priority = ORDER.get(control);
164
- while (pending.size) {
165
- let compute;
166
- for (const item of pending)
167
- if (!compute || priority.get(item) < priority.get(compute))
168
- compute = item;
169
- pending.delete(compute);
170
- const key = INFO.get(compute);
171
- if (!control.frame.has(key))
172
- compute();
173
- }
174
- pending.clear();
234
+ });
175
235
  }
176
236
 
177
- const Oops$d = issues({
237
+ const Oops$a = issues({
178
238
  BadCallback: () => `Callback for effect-callback may only return a function.`
179
239
  });
180
240
  function createEffect(model, callback, keys) {
@@ -188,7 +248,7 @@ function createEffect(model, callback, keys) {
188
248
  if (unSet instanceof Promise)
189
249
  unSet = undefined;
190
250
  if (unSet && typeof unSet !== "function")
191
- throw Oops$d.BadCallback();
251
+ throw Oops$a.BadCallback();
192
252
  }
193
253
  function invoke() {
194
254
  if (busy)
@@ -212,10 +272,11 @@ function createEffect(model, callback, keys) {
212
272
  return invoke;
213
273
  });
214
274
  }
215
- const sub = controller.subscribe(() => invoke);
275
+ const sub = new Subscriber(controller, () => invoke);
216
276
  model = sub.proxy;
217
277
  invoke();
218
- return sub.commit();
278
+ sub.commit();
279
+ return () => sub.release();
219
280
  });
220
281
  }
221
282
  function createValueEffect(callback) {
@@ -231,11 +292,11 @@ function createValueEffect(callback) {
231
292
  if (typeof out == "function")
232
293
  unSet = out;
233
294
  else
234
- throw Oops$d.BadCallback();
295
+ throw Oops$a.BadCallback();
235
296
  };
236
297
  }
237
298
 
238
- const Oops$c = issues({
299
+ const Oops$9 = issues({
239
300
  Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
240
301
  KeysExpected: (key) => `Key "${key}" was expected in current update.`,
241
302
  StrictUpdate: () => `Expected update but none in progress.`,
@@ -271,13 +332,13 @@ function awaitUpdate(source, arg1, arg2) {
271
332
  const timeout = (message) => {
272
333
  const k = keys ? keys.join(", ") : "any";
273
334
  removeListener();
274
- reject(Oops$c.Timeout(k, message));
335
+ reject(Oops$9.Timeout(k, message));
275
336
  };
276
337
  const removeListener = control(source, controller => {
277
338
  const pending = controller.frame;
278
339
  if (keys === null) {
279
340
  if (pending.size)
280
- reject(Oops$c.StrictNoUpdate());
341
+ reject(Oops$9.StrictNoUpdate());
281
342
  else
282
343
  resolve(null);
283
344
  return;
@@ -285,7 +346,7 @@ function awaitUpdate(source, arg1, arg2) {
285
346
  if (keys) {
286
347
  if (keys.length) {
287
348
  if (arg2 === 0 && single && !pending.has(keys[0])) {
288
- reject(Oops$c.KeysExpected(keys[0]));
349
+ reject(Oops$9.KeysExpected(keys[0]));
289
350
  return;
290
351
  }
291
352
  else
@@ -297,7 +358,7 @@ function awaitUpdate(source, arg1, arg2) {
297
358
  }
298
359
  }
299
360
  else if (!pending.size && arg1 === true || arg2 === 0) {
300
- reject(Oops$c.StrictUpdate());
361
+ reject(Oops$9.StrictUpdate());
301
362
  return;
302
363
  }
303
364
  else
@@ -320,67 +381,7 @@ function awaitUpdate(source, arg1, arg2) {
320
381
  });
321
382
  }
322
383
 
323
- const REGISTER$1 = new WeakMap();
324
- class Subscriber {
325
- constructor(parent, onUpdate) {
326
- this.parent = parent;
327
- this.onUpdate = onUpdate;
328
- this.active = false;
329
- this.dependant = new Set();
330
- this.watch = new Map();
331
- const proxy = create(parent.subject);
332
- const reset = () => this.latest = undefined;
333
- REGISTER$1.set(proxy, this);
334
- defineProperty(this, "proxy", {
335
- configurable: true,
336
- get() {
337
- setTimeout(reset, 0);
338
- return proxy;
339
- }
340
- });
341
- }
342
- get using() {
343
- return Array.from(this.watch.keys());
344
- }
345
- add(key, value) {
346
- if (value !== undefined)
347
- this.watch.set(key, value);
348
- else if (!this.watch.has(key))
349
- this.watch.set(key, true);
350
- }
351
- commit() {
352
- const release = this.parent.addListener(key => {
353
- if (this.active)
354
- this.onEvent(key);
355
- });
356
- this.active = true;
357
- this.dependant.forEach(x => x.commit());
358
- return this.release = () => {
359
- this.dependant.forEach(x => x.release());
360
- release();
361
- };
362
- }
363
- onEvent(key) {
364
- const { parent, watch } = this;
365
- let handler = watch.get(key);
366
- if (typeof handler == "function")
367
- handler = handler();
368
- if (handler) {
369
- const notify = this.onUpdate(key, parent);
370
- if (notify) {
371
- parent.waiting.add(update => {
372
- this.latest = update.filter(k => watch.has(k));
373
- });
374
- parent.waiting.add(notify);
375
- }
376
- }
377
- }
378
- }
379
- function subscriber(from) {
380
- return REGISTER$1.get(from);
381
- }
382
-
383
- const Oops$b = issues({
384
+ const Oops$8 = issues({
384
385
  NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
385
386
  });
386
387
  class Model {
@@ -438,7 +439,7 @@ class Model {
438
439
  return {
439
440
  then: (callback) => {
440
441
  if (!callback)
441
- throw Oops$b.NoChaining();
442
+ throw Oops$8.NoChaining();
442
443
  controller.waiting.add(callback);
443
444
  }
444
445
  };
@@ -471,11 +472,150 @@ class Model {
471
472
  maybe.prototype instanceof this);
472
473
  }
473
474
  }
474
- defineProperty(Model.prototype, "toString", {
475
- value() {
476
- return this.constructor.name;
477
- }
478
- });
475
+ defineProperty(Model.prototype, "toString", {
476
+ value() {
477
+ return this.constructor.name;
478
+ }
479
+ });
480
+ const FindInstruction = new WeakMap([
481
+ [Model, getParentForGetInstruction]
482
+ ]);
483
+
484
+ const Oops$7 = issues({
485
+ PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
486
+ Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
487
+ });
488
+ function get(arg0, arg1) {
489
+ return add(function get(key) {
490
+ const { subject, state } = this;
491
+ // Easy mistake, using a peer, will always be unresolved.
492
+ if (typeof arg0 == "symbol")
493
+ throw Oops$7.PeerNotAllowed(subject, key);
494
+ let source;
495
+ const sourceRequired = arg1 !== false;
496
+ if (arg0 instanceof Model) {
497
+ source = () => arg0;
498
+ if (typeof arg1 !== "function")
499
+ throw new Error(`Factory argument cannot be ${arg1}`);
500
+ }
501
+ else if (Model.isTypeof(arg0)) {
502
+ source = find(arg0, subject, sourceRequired);
503
+ }
504
+ else if (typeof arg0 == "function") {
505
+ arg1 = arg0.call(subject, key, subject);
506
+ source = () => subject;
507
+ }
508
+ if (typeof arg1 == "function")
509
+ return getComputed(key, this, source, arg1);
510
+ else {
511
+ const init = source((got) => {
512
+ state.set(key, got);
513
+ this.update(key);
514
+ });
515
+ // TODO: remove fixes suspense test
516
+ if (init || arg1 === false)
517
+ state.set(key, init);
518
+ return getRecursive(key, this);
519
+ }
520
+ });
521
+ }
522
+ function getComputed(key, parent, source, setter) {
523
+ const { state } = parent;
524
+ let sub;
525
+ let order = ORDER.get(parent);
526
+ let pending = KEYS.get(parent);
527
+ let instance;
528
+ if (!order)
529
+ ORDER.set(parent, order = new Map());
530
+ if (!pending)
531
+ KEYS.set(parent, pending = new Set());
532
+ const compute = (initial) => {
533
+ try {
534
+ return setter.call(sub.proxy, sub.proxy);
535
+ }
536
+ catch (err) {
537
+ Oops$7.Failed(instance, key, initial).warn();
538
+ throw err;
539
+ }
540
+ };
541
+ const create = () => {
542
+ // TODO: replace create with a cleanup function
543
+ const got = source(create);
544
+ if (!got)
545
+ throw suspend(parent, key);
546
+ instance = got;
547
+ sub = new Subscriber(control(instance), (_, control) => {
548
+ if (control !== parent)
549
+ refresh();
550
+ else
551
+ pending.add(refresh);
552
+ });
553
+ sub.watch.set(key, false);
554
+ try {
555
+ const value = compute(true);
556
+ state.set(key, value);
557
+ return value;
558
+ }
559
+ finally {
560
+ sub.commit();
561
+ order.set(refresh, order.size);
562
+ }
563
+ };
564
+ const refresh = () => {
565
+ let value;
566
+ try {
567
+ value = compute(false);
568
+ }
569
+ catch (e) {
570
+ console.error(e);
571
+ }
572
+ finally {
573
+ if (state.get(key) !== value) {
574
+ state.set(key, value);
575
+ parent.update(key);
576
+ return value;
577
+ }
578
+ }
579
+ };
580
+ INFO.set(refresh, key);
581
+ return () => {
582
+ if (pending.has(refresh)) {
583
+ pending.delete(refresh);
584
+ refresh();
585
+ }
586
+ return sub ? state.get(key) : create();
587
+ };
588
+ }
589
+ const INFO = new WeakMap();
590
+ const KEYS = new WeakMap();
591
+ const ORDER = new WeakMap();
592
+ function flush(control) {
593
+ const pending = KEYS.get(control);
594
+ if (!pending || !pending.size)
595
+ return;
596
+ const priority = ORDER.get(control);
597
+ while (pending.size) {
598
+ let compute;
599
+ for (const item of pending)
600
+ if (!compute || priority.get(item) < priority.get(compute))
601
+ compute = item;
602
+ pending.delete(compute);
603
+ const key = INFO.get(compute);
604
+ if (!control.frame.has(key))
605
+ compute();
606
+ }
607
+ pending.clear();
608
+ }
609
+ // TODO: collapse this function when MVC is merged into Model.
610
+ function find(type, relativeTo, required) {
611
+ let T = type;
612
+ do {
613
+ T = getPrototypeOf(T);
614
+ const getter = FindInstruction.get(T);
615
+ if (getter)
616
+ return getter(type, relativeTo, required);
617
+ } while (T.prototype instanceof Model);
618
+ }
479
619
 
480
620
  const REGISTER = new WeakMap();
481
621
  const PENDING = new Map();
@@ -487,9 +627,6 @@ class Control {
487
627
  this.followers = new Set();
488
628
  REGISTER.set(subject, this);
489
629
  }
490
- subscribe(callback) {
491
- return new Subscriber(this, callback);
492
- }
493
630
  watch(key) {
494
631
  const { subject, state } = this;
495
632
  const { value } = getOwnPropertyDescriptor(subject, key);
@@ -500,7 +637,7 @@ class Control {
500
637
  if (instruction) {
501
638
  delete subject[key];
502
639
  PENDING.delete(value);
503
- instruction.call(this, key, this);
640
+ instruction(this, key);
504
641
  }
505
642
  return;
506
643
  }
@@ -514,9 +651,13 @@ class Control {
514
651
  set: this.ref(key),
515
652
  get() {
516
653
  const sub = subscriber(this);
517
- if (sub)
518
- sub.add(key);
519
- return state.get(key);
654
+ const value = state.get(key);
655
+ if (sub) {
656
+ sub.follow(key);
657
+ if (value === undefined && sub.strict)
658
+ throw suspend(this, key);
659
+ }
660
+ return value;
520
661
  }
521
662
  });
522
663
  }
@@ -574,6 +715,8 @@ class Control {
574
715
  listeners.forEach(x => x(null, this));
575
716
  }
576
717
  }
718
+ Control.get = controller;
719
+ Control.for = control;
577
720
  function controller(from) {
578
721
  if ("is" in from)
579
722
  from = from.is;
@@ -603,68 +746,6 @@ function control(subject, cb) {
603
746
  return cb ? cb(control) : control;
604
747
  }
605
748
 
606
- const Parent = new WeakMap();
607
- const Oops$a = issues({
608
- BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`
609
- });
610
- function getRecursive(key, from) {
611
- const context = new WeakMap();
612
- const { state } = from;
613
- return (local) => {
614
- if (!local)
615
- return state.get(key);
616
- if (!context.has(local)) {
617
- let reset;
618
- const init = () => {
619
- if (reset)
620
- reset();
621
- const value = state.get(key);
622
- if (value && controller(value)) {
623
- const child = control(value).subscribe(local.onUpdate);
624
- if (local.active)
625
- child.commit();
626
- local.dependant.add(child);
627
- context.set(local, child.proxy);
628
- reset = () => {
629
- child.release();
630
- local.dependant.delete(child);
631
- context.set(local, undefined);
632
- reset = undefined;
633
- };
634
- }
635
- return true;
636
- };
637
- local.add(key, init);
638
- init();
639
- }
640
- return context.get(local);
641
- };
642
- }
643
- function setRecursive(controller, key, initial) {
644
- const { state, subject } = controller;
645
- const Type = initial.constructor;
646
- let get;
647
- const onUpdate = (next) => {
648
- state.set(key, next);
649
- if (!(next instanceof Type))
650
- throw Oops$a.BadAssignment(`${subject}.${key}`, Type.name, String(next));
651
- get = getRecursive(key, controller);
652
- Parent.set(next, subject);
653
- control(next);
654
- return true;
655
- };
656
- onUpdate(initial);
657
- defineProperty(subject, key, {
658
- set: controller.ref(key, onUpdate),
659
- get() {
660
- const local = subscriber(this);
661
- if (local)
662
- local.add(key);
663
- return get(local);
664
- }
665
- });
666
- }
667
-
668
749
  /**
669
750
  * Run instruction as controller sets itself up.
670
751
  * This will specialize the behavior of a given property.
@@ -672,53 +753,42 @@ function setRecursive(controller, key, initial) {
672
753
  function add(instruction, label) {
673
754
  const name = label || instruction.name || "pending";
674
755
  const placeholder = Symbol(`${name} instruction`);
675
- function setup(key) {
676
- const { subject, state } = this;
677
- let output = instruction.call(this, key, this);
756
+ PENDING.set(placeholder, (control, key) => {
757
+ let output = instruction.call(control, key, control);
758
+ if (!output)
759
+ return undefined;
678
760
  if (typeof output == "function")
679
761
  output = { get: output };
680
- if (typeof output != "object")
681
- return;
682
- if ("explicit" in output && output.explicit) {
683
- defineProperty(subject, key, output);
684
- return false;
685
- }
686
- let { get: onGet, set: onSet, suspend: shouldSuspend } = output;
687
762
  if ("value" in output)
688
- state.set(key, output.value);
689
- if ("recursive" in output && output.recursive)
690
- onGet = getRecursive(key, this);
691
- if ("destroy" in output) {
692
- const { destroy } = output;
693
- if (destroy)
694
- this.addListener((key) => {
695
- if (key == null)
696
- destroy();
697
- });
698
- }
699
- const control = this;
700
- defineProperty(subject, key, {
701
- enumerable: output.enumerable,
702
- set: onSet === false
763
+ control.state.set(key, output.value);
764
+ let { enumerable, get, set } = output;
765
+ defineProperty(control.subject, key, {
766
+ enumerable,
767
+ set: set === false
703
768
  ? undefined
704
- : this.ref(key, onSet),
769
+ : control.ref(key, set),
705
770
  get() {
706
- if (!state.has(key) && shouldSuspend)
707
- throw suspend(control, key);
708
771
  const local = subscriber(this);
709
772
  if (local)
710
- local.add(key);
711
- return onGet
712
- ? onGet(local)
713
- : state.get(key);
773
+ local.follow(key);
774
+ try {
775
+ const value = get ? get(local) : control.state.get(key);
776
+ if (value === undefined && local && local.strict === true)
777
+ throw suspend(control, key);
778
+ return value;
779
+ }
780
+ catch (err) {
781
+ if (err instanceof Promise && local && local.strict === false)
782
+ return;
783
+ throw err;
784
+ }
714
785
  }
715
786
  });
716
- }
717
- PENDING.set(placeholder, setup);
787
+ });
718
788
  return placeholder;
719
789
  }
720
790
 
721
- /*! *****************************************************************************
791
+ /******************************************************************************
722
792
  Copyright (c) Microsoft Corporation.
723
793
 
724
794
  Permission to use, copy, modify, and/or distribute this software for any
@@ -743,7 +813,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
743
813
  });
744
814
  }
745
815
 
746
- const Oops$9 = issues({
816
+ const Oops$6 = issues({
747
817
  DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
748
818
  });
749
819
  function run(task) {
@@ -751,7 +821,7 @@ function run(task) {
751
821
  let pending = false;
752
822
  const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
753
823
  if (pending)
754
- return Promise.reject(Oops$9.DuplicatePending(key));
824
+ return Promise.reject(Oops$6.DuplicatePending(key));
755
825
  pending = true;
756
826
  this.update(key);
757
827
  try {
@@ -773,106 +843,6 @@ function run(task) {
773
843
  });
774
844
  }
775
845
 
776
- const Oops$8 = issues({
777
- NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
778
- });
779
- function factoryMode(self, value, key, required) {
780
- const { subject, state } = self;
781
- let pending;
782
- let error;
783
- if (value instanceof Promise) {
784
- state.set(key, undefined);
785
- pending = value
786
- .catch(err => error = err)
787
- .then(val => {
788
- state.set(key, val);
789
- return val;
790
- })
791
- .finally(() => {
792
- pending = undefined;
793
- self.update(key);
794
- });
795
- }
796
- else
797
- state.set(key, value);
798
- const suspend = () => {
799
- if (required === false)
800
- return undefined;
801
- const issue = Oops$8.NotReady(subject, key);
802
- assign(pending, {
803
- message: issue.message,
804
- stack: issue.stack
805
- });
806
- throw pending;
807
- };
808
- return () => {
809
- if (error)
810
- throw error;
811
- if (pending)
812
- return suspend();
813
- if (state.has(key))
814
- return state.get(key);
815
- };
816
- }
817
-
818
- const Oops$7 = issues({
819
- PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
820
- ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
821
- Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
822
- });
823
- function get(arg0, arg1, arg2) {
824
- return add(function get(key) {
825
- const { subject } = this;
826
- const computeRequired = arg1 === true || arg2 === true;
827
- const factoryRequired = arg1 !== false && arg2 !== false;
828
- let getter;
829
- // Easy mistake, using a peer, will always be unresolved.
830
- if (typeof arg0 == "symbol")
831
- throw Oops$7.PeerNotAllowed(subject, key);
832
- // if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
833
- // throw Oops.BadSource(subject, key, arg0);
834
- this.state.set(key, undefined);
835
- const init = () => {
836
- let source = this;
837
- let setter;
838
- if (typeof arg0 == "function") {
839
- let result = mayRetry(arg0.bind(subject, key, subject));
840
- if (typeof result == "function")
841
- setter = result;
842
- else {
843
- getter = factoryMode(this, result, key, factoryRequired);
844
- return;
845
- }
846
- }
847
- else if (arg0 instanceof Promise) {
848
- getter = factoryMode(this, arg0, key, factoryRequired);
849
- return;
850
- }
851
- else if (typeof arg1 == "function") {
852
- // replace source controller in-case it is different
853
- source = control(arg0);
854
- setter = arg1;
855
- }
856
- else
857
- throw new Error(`Factory argument cannot be ${arg1}`);
858
- getter = computeMode(this, source, setter, key, computeRequired);
859
- };
860
- if (typeof arg0 == "function" && computeRequired)
861
- try {
862
- init();
863
- }
864
- catch (err) {
865
- Oops$7.ComputeFailed(subject, key).warn();
866
- throw err;
867
- }
868
- return () => {
869
- if (!getter)
870
- init();
871
- return getter();
872
- };
873
- });
874
- }
875
-
876
846
  function ref(arg, mapper) {
877
847
  return add(function ref(key) {
878
848
  let value = {};
@@ -892,7 +862,7 @@ function ref(arg, mapper) {
892
862
  value: createRef(this, key)
893
863
  });
894
864
  });
895
- return { value, explicit: true };
865
+ defineProperty(this.subject, key, { value });
896
866
  });
897
867
  }
898
868
  function createRef(src, key, cb) {
@@ -904,16 +874,78 @@ function createRef(src, key, cb) {
904
874
  return refObjectFunction;
905
875
  }
906
876
 
877
+ const Oops$5 = issues({
878
+ ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
879
+ NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
880
+ });
907
881
  function set(value, argument) {
908
- if (!(1 in arguments)) {
909
- argument = value;
910
- value = undefined;
911
- }
912
882
  return add(function set(key) {
883
+ const { state, subject } = this;
884
+ if (typeof value == "function" || value instanceof Promise) {
885
+ const required = argument !== false;
886
+ let getter;
887
+ const init = () => {
888
+ try {
889
+ if (typeof value == "function")
890
+ value = mayRetry(value.bind(subject, key, subject));
891
+ let pending;
892
+ let error;
893
+ if (value instanceof Promise) {
894
+ state.set(key, undefined);
895
+ pending = value
896
+ .catch(err => error = err)
897
+ .then(val => {
898
+ state.set(key, val);
899
+ return val;
900
+ })
901
+ .finally(() => {
902
+ pending = undefined;
903
+ this.update(key);
904
+ });
905
+ }
906
+ else
907
+ state.set(key, value);
908
+ const suspend = () => {
909
+ if (required === false)
910
+ return undefined;
911
+ const issue = Oops$5.NotReady(subject, key);
912
+ assign(pending, {
913
+ message: issue.message,
914
+ stack: issue.stack
915
+ });
916
+ throw pending;
917
+ };
918
+ getter = () => {
919
+ if (error)
920
+ throw error;
921
+ if (pending)
922
+ return suspend();
923
+ if (state.has(key))
924
+ return state.get(key);
925
+ };
926
+ }
927
+ catch (err) {
928
+ Oops$5.ComputeFailed(subject, key).warn();
929
+ throw err;
930
+ }
931
+ };
932
+ if (argument === true)
933
+ init();
934
+ return () => {
935
+ if (!getter)
936
+ init();
937
+ return getter();
938
+ };
939
+ }
913
940
  if (value !== undefined)
914
- this.state.set(key, value);
941
+ state.set(key, value);
915
942
  return {
916
- suspend: true,
943
+ get: () => {
944
+ if (state.has(key))
945
+ return state.get(key);
946
+ else
947
+ throw suspend(this, key);
948
+ },
917
949
  set: typeof argument == "function"
918
950
  ? createValueEffect(argument)
919
951
  : undefined
@@ -957,7 +989,7 @@ function keyed(control, property, initial) {
957
989
  }
958
990
  }
959
991
  }
960
- local.add(property, false);
992
+ local.follow(property, false);
961
993
  local.dependant.add({
962
994
  commit() {
963
995
  if (using.size === 0)
@@ -973,6 +1005,12 @@ function keyed(control, property, initial) {
973
1005
  context.set(local, proxy);
974
1006
  return proxy;
975
1007
  }
1008
+ control.addListener(key => {
1009
+ if (key === null) {
1010
+ update.clear();
1011
+ context.clear();
1012
+ }
1013
+ });
976
1014
  return {
977
1015
  value: initial,
978
1016
  get(local) {
@@ -985,10 +1023,6 @@ function keyed(control, property, initial) {
985
1023
  managed = init(next);
986
1024
  context.clear();
987
1025
  emit(ANY);
988
- },
989
- destroy() {
990
- update.clear();
991
- context.clear();
992
1026
  }
993
1027
  };
994
1028
  }
@@ -1067,11 +1101,11 @@ function createProxy(emit, watch) {
1067
1101
  };
1068
1102
  }
1069
1103
 
1070
- const Oops$6 = issues({
1104
+ const Oops$4 = issues({
1071
1105
  BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
1072
1106
  NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
1073
1107
  });
1074
- function use$1(input, argument) {
1108
+ function use(input, argument) {
1075
1109
  return add(function use(key) {
1076
1110
  const { state, subject } = this;
1077
1111
  const required = argument !== false;
@@ -1083,7 +1117,7 @@ function use$1(input, argument) {
1083
1117
  input = new input();
1084
1118
  }
1085
1119
  else if (input && typeof input !== "object")
1086
- throw Oops$6.BadArgument(typeof input);
1120
+ throw Oops$4.BadArgument(typeof input);
1087
1121
  if (input instanceof Map || input instanceof Set)
1088
1122
  return keyed(this, key, input);
1089
1123
  const onUpdate = (next) => {
@@ -1100,7 +1134,7 @@ function use$1(input, argument) {
1100
1134
  const suspend = () => {
1101
1135
  if (required === false)
1102
1136
  return;
1103
- const issue = Oops$6.NotReady(subject, key);
1137
+ const issue = Oops$4.NotReady(subject, key);
1104
1138
  assign(pending, {
1105
1139
  message: issue.message,
1106
1140
  stack: issue.stack
@@ -1145,33 +1179,11 @@ function use$1(input, argument) {
1145
1179
  });
1146
1180
  }
1147
1181
 
1148
- const Oops$5 = issues({
1149
- Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
1150
- Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
1151
- });
1152
- function has(Type, required) {
1153
- return add(function parent() {
1154
- const child = this.subject;
1155
- const value = Parent.get(child);
1156
- const expected = Type.name;
1157
- if (!value) {
1158
- if (required !== false)
1159
- throw Oops$5.Required(expected, child);
1160
- }
1161
- else if (!(value instanceof Type))
1162
- throw Oops$5.Unexpected(expected, child, value);
1163
- return { value };
1164
- });
1165
- }
1166
-
1167
- const Oops$4 = issues({
1168
- NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
1169
- });
1170
- class Lookup {
1182
+ class Register {
1171
1183
  constructor() {
1172
1184
  this.table = new Map();
1173
1185
  }
1174
- key(T) {
1186
+ has(T) {
1175
1187
  let key = this.table.get(T);
1176
1188
  if (!key) {
1177
1189
  key = Symbol(T.name);
@@ -1180,22 +1192,9 @@ class Lookup {
1180
1192
  return key;
1181
1193
  }
1182
1194
  get(Type) {
1183
- return this[this.key(Type)];
1184
- }
1185
- has(key, input, callback) {
1186
- if (MVC.isTypeof(input) && input.global)
1187
- return input.new();
1188
- if (this.register.get(key) === input)
1189
- return typeof input == "object"
1190
- ? input
1191
- : this.get(input);
1192
- const instance = this.add(input);
1193
- this.register.set(key, input);
1194
- if (callback)
1195
- callback(instance);
1196
- return instance;
1195
+ return this[this.has(Type)];
1197
1196
  }
1198
- add(input) {
1197
+ add(input, key) {
1199
1198
  let writable = true;
1200
1199
  let T;
1201
1200
  let I;
@@ -1204,12 +1203,12 @@ class Lookup {
1204
1203
  I = new input();
1205
1204
  }
1206
1205
  else {
1207
- I = input;
1206
+ I = input.is;
1208
1207
  T = I.constructor;
1209
1208
  writable = false;
1210
1209
  }
1211
1210
  do {
1212
- const key = this.key(T);
1211
+ const key = this.has(T);
1213
1212
  defineProperty(this, key, {
1214
1213
  configurable: true,
1215
1214
  value: this.hasOwnProperty(key) ? null : I,
@@ -1217,6 +1216,8 @@ class Lookup {
1217
1216
  });
1218
1217
  T = getPrototypeOf(T);
1219
1218
  } while (T !== Model);
1219
+ if (key !== undefined)
1220
+ this.register.set(key, input);
1220
1221
  return I;
1221
1222
  }
1222
1223
  push() {
@@ -1230,52 +1231,74 @@ class Lookup {
1230
1231
  const entry = getOwnPropertyDescriptor(this, key);
1231
1232
  if (entry.writable && entry.value)
1232
1233
  items.add(entry.value);
1234
+ delete this[key];
1233
1235
  }
1234
1236
  for (const model of items)
1235
1237
  model.end();
1236
1238
  }
1239
+ delete(instance) {
1240
+ for (const key of getOwnPropertySymbols(this)) {
1241
+ const entry = getOwnPropertyDescriptor(this, key);
1242
+ if (entry.value === instance)
1243
+ delete this[key];
1244
+ }
1245
+ }
1246
+ }
1247
+ const Global$1 = new Register();
1248
+
1249
+ const Oops$3 = issues({
1250
+ AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`,
1251
+ DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.new() before attempting to access, or consider using ${name}.use() instead.`,
1252
+ NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
1253
+ });
1254
+ const LookupContext = React__default["default"].createContext(Global$1);
1255
+ function useLookup() {
1256
+ try {
1257
+ return React__default["default"].useContext(LookupContext);
1258
+ }
1259
+ catch (err) {
1260
+ return Global$1;
1261
+ }
1237
1262
  }
1238
- const LookupContext = React__default["default"].createContext(new Lookup());
1239
- const useLookup = () => React__default["default"].useContext(LookupContext);
1240
1263
  function useContext(Type, required) {
1241
1264
  const instance = useLookup().get(Type);
1242
1265
  if (!instance && required !== false)
1243
- throw Oops$4.NotFound(Type.name);
1266
+ throw MVC.isTypeof(Type) && Type.global
1267
+ ? Oops$3.DoesNotExist(Type.name)
1268
+ : Oops$3.NotFound(Type.name);
1244
1269
  return instance;
1245
1270
  }
1246
1271
 
1247
- const Oops$3 = issues({
1272
+ const Oops$2 = issues({
1248
1273
  NotAllowed: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
1249
- 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.`
1274
+ AmbientRequired: (requested, requester) => `Attempted to find an instance of ${requested} in context. It is required by ${requester}, but one could not be found.`
1250
1275
  });
1251
1276
  const Pending = new WeakMap();
1252
1277
  const Applied = new WeakMap();
1253
- function tap(type, argument) {
1254
- return add(function tap(key) {
1255
- if (MVC.isTypeof(type) && type.global)
1256
- return {
1257
- recursive: true,
1258
- value: type.get()
1259
- };
1260
- const { subject } = this;
1261
- if (subject.constructor.global)
1262
- throw Oops$3.NotAllowed(subject, type.name);
1263
- getPending(subject).push(context => {
1264
- let instance = context.get(type);
1265
- if (typeof argument == "function") {
1266
- if (argument(instance) === false)
1267
- instance = undefined;
1278
+ function getContextForGetInstruction(type, relativeTo, required) {
1279
+ let item = getParent(type, relativeTo);
1280
+ return (refresh) => {
1281
+ if (item)
1282
+ return item;
1283
+ findRelative(relativeTo, type, got => {
1284
+ if (got) {
1285
+ item = got;
1286
+ refresh(got);
1268
1287
  }
1269
- else if (!instance && argument)
1270
- throw Oops$3.AmbientRequired(type.name, subject, key);
1271
- this.state.set(key, instance);
1272
- this.update(key);
1288
+ else if (required)
1289
+ throw Oops$2.AmbientRequired(type.name, relativeTo);
1290
+ });
1291
+ };
1292
+ }
1293
+ function findRelative(from, type, callback) {
1294
+ if (MVC.isTypeof(type) && type.global)
1295
+ callback(Global$1.get(type));
1296
+ else if (from.constructor.global)
1297
+ throw Oops$2.NotAllowed(from, type.name);
1298
+ else
1299
+ getPending(from).push(context => {
1300
+ callback(context.get(type));
1273
1301
  });
1274
- return {
1275
- recursive: true,
1276
- suspend: true
1277
- };
1278
- });
1279
1302
  }
1280
1303
  function usePeerContext(subject) {
1281
1304
  if (Applied.has(subject)) {
@@ -1299,7 +1322,7 @@ function getPending(subject) {
1299
1322
  return pending;
1300
1323
  }
1301
1324
 
1302
- function useNew(source, arg1, arg2) {
1325
+ function useModel(source, arg1, arg2) {
1303
1326
  const instance = React__default["default"].useMemo(() => {
1304
1327
  const callback = arg2 || arg1;
1305
1328
  const instance = Model.isTypeof(source)
@@ -1312,7 +1335,7 @@ function useNew(source, arg1, arg2) {
1312
1335
  }, []);
1313
1336
  usePeerContext(instance);
1314
1337
  if (Array.isArray(arg1)) {
1315
- const update = React.useState(0)[1];
1338
+ const update = React__default["default"].useState(0)[1];
1316
1339
  React__default["default"].useLayoutEffect(() => {
1317
1340
  if (arg1.length && instance instanceof Model)
1318
1341
  instance.on(arg1, () => update(x => x + 1));
@@ -1326,19 +1349,10 @@ function useNew(source, arg1, arg2) {
1326
1349
  const state = React__default["default"].useState(0);
1327
1350
  const local = React__default["default"].useMemo(() => {
1328
1351
  const refresh = state[1].bind(null, x => x + 1);
1329
- return control(instance).subscribe(() => refresh);
1352
+ return new Subscriber(control(instance), () => refresh);
1330
1353
  }, []);
1331
- if (typeof arg1 == "object") {
1332
- const { waiting, subject } = local.parent;
1333
- let keys = arg2;
1334
- local.active = false;
1335
- if (!keys)
1336
- keys = getOwnPropertyNames(subject);
1337
- for (const key of keys)
1338
- if (key in arg1)
1339
- subject[key] = arg1[key];
1340
- waiting.add(() => local.active = true);
1341
- }
1354
+ if (typeof arg1 == "object")
1355
+ local.apply(arg1, arg2);
1342
1356
  React__default["default"].useLayoutEffect(() => {
1343
1357
  local.commit();
1344
1358
  return () => {
@@ -1350,19 +1364,22 @@ function useNew(source, arg1, arg2) {
1350
1364
  return local.proxy;
1351
1365
  }
1352
1366
 
1353
- function use(init, deps) {
1367
+ function useTap(source, arg1, arg2) {
1368
+ const instance = typeof source == "object"
1369
+ ? source
1370
+ : "get" in source
1371
+ ? source.get()
1372
+ : source();
1373
+ const deps = [uid(instance)];
1354
1374
  const state = React__default["default"].useState(0);
1355
- return React__default["default"].useMemo(() => {
1356
- return init(state[1].bind(null, x => x + 1));
1357
- }, deps);
1358
- }
1359
-
1360
- function useCompute(source, compute, suspend) {
1361
- const deps = [uid(source)];
1362
- const local = use(refresh => {
1363
- const sub = control(source).subscribe(() => update);
1375
+ const local = React__default["default"].useMemo(() => {
1376
+ const refresh = state[1].bind(null, x => x + 1);
1377
+ const controller = control(instance);
1378
+ if (typeof arg1 != "function")
1379
+ return new Subscriber(controller, () => refresh, arg1);
1380
+ const sub = new Subscriber(controller, () => update);
1364
1381
  const spy = sub.proxy;
1365
- let make = () => compute.call(spy, spy, forceUpdate);
1382
+ let make = () => arg1.call(spy, spy, forceUpdate);
1366
1383
  function forceUpdate(passthru) {
1367
1384
  if (typeof passthru == "function")
1368
1385
  passthru = passthru();
@@ -1393,7 +1410,7 @@ function useCompute(source, compute, suspend) {
1393
1410
  if (typeof value == "function") {
1394
1411
  const get = value;
1395
1412
  sub.watch.clear();
1396
- compute = () => get();
1413
+ arg1 = () => get();
1397
1414
  value = get();
1398
1415
  }
1399
1416
  if (value instanceof Promise) {
@@ -1404,7 +1421,7 @@ function useCompute(source, compute, suspend) {
1404
1421
  sub.commit();
1405
1422
  update = () => {
1406
1423
  const next = make();
1407
- if (value != next)
1424
+ if (notEqual(value, next))
1408
1425
  reassign(next);
1409
1426
  };
1410
1427
  }
@@ -1412,7 +1429,7 @@ function useCompute(source, compute, suspend) {
1412
1429
  get() {
1413
1430
  if (value !== undefined)
1414
1431
  return value;
1415
- if (suspend)
1432
+ if (arg2)
1416
1433
  throw new Promise(res => retry = res);
1417
1434
  return null;
1418
1435
  }
@@ -1421,67 +1438,47 @@ function useCompute(source, compute, suspend) {
1421
1438
  }, deps);
1422
1439
  if (!local)
1423
1440
  return null;
1424
- React__default["default"].useLayoutEffect(() => local.release, deps);
1441
+ React__default["default"].useLayoutEffect(() => {
1442
+ local.commit();
1443
+ return () => local.release();
1444
+ }, deps);
1425
1445
  return local.proxy;
1426
- }
1427
-
1428
- function useTap(source, arg1, arg2) {
1429
- const instance = typeof source == "object"
1430
- ? source
1431
- : "get" in source
1432
- ? source.get()
1433
- : useContext(source);
1434
- return typeof arg1 == "function"
1435
- ? useCompute(instance, arg1, arg2)
1436
- : useSubscribe(instance, arg1, arg2);
1437
1446
  }
1438
- function useSubscribe(source, path, expect) {
1439
- const deps = [uid(source)];
1440
- const local = use(refresh => (control(source).subscribe(() => refresh)), deps);
1441
- React__default["default"].useLayoutEffect(() => local.commit(), deps);
1442
- if (path === undefined)
1443
- return local.proxy;
1444
- const value = local.proxy[path];
1445
- if (value === undefined && expect)
1446
- throw suspend(local.parent, path);
1447
- return value;
1448
- }
1447
+ /** Values are not equal for purposes of a refresh. */
1448
+ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
1449
+ !Array.isArray(b) ||
1450
+ a.length !== b.length ||
1451
+ a.some((x, i) => x !== b[i])));
1449
1452
 
1450
- const Global$1 = new WeakMap();
1451
- const Oops$2 = issues({
1452
- DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.new() before attempting to access, or consider using ${name}.use() instead.`,
1453
- AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
1454
- });
1455
1453
  class MVC extends Model {
1456
1454
  end(force) {
1457
1455
  const type = this.constructor;
1458
1456
  if (type.keepAlive && !force)
1459
1457
  return false;
1460
1458
  super.end();
1461
- Global$1.delete(type);
1459
+ Global$1.delete(this);
1462
1460
  return true;
1463
1461
  }
1464
1462
  static new(...args) {
1465
- if (Global$1.has(this))
1463
+ const exists = Global$1.get(this);
1464
+ if (exists)
1466
1465
  if (this.keepAlive)
1467
- return Global$1.get(this);
1466
+ return exists;
1468
1467
  else
1469
- throw Oops$2.AlreadyExists(this.name);
1468
+ throw Oops$3.AlreadyExists(this.name);
1470
1469
  const instance = super.new(...args);
1471
1470
  if (this.global)
1472
- Global$1.set(this, instance);
1471
+ Global$1.add(instance);
1473
1472
  return instance;
1474
1473
  }
1475
1474
  static get(arg1, arg2) {
1476
- let instance;
1477
1475
  const required = arg1 === undefined || arg1 === true;
1478
- if (this.global) {
1479
- instance = Global$1.get(this);
1480
- if (!instance && required)
1481
- throw Oops$2.DoesNotExist(this.name);
1482
- }
1483
- else
1484
- instance = useContext(this, required);
1476
+ const instance = useContext(this, required);
1477
+ if (typeof arg1 === "function" && instance)
1478
+ callback(arg1);
1479
+ else if (arg2)
1480
+ callback(arg2);
1481
+ return instance;
1485
1482
  function callback(effect) {
1486
1483
  try {
1487
1484
  React__default["default"].useLayoutEffect(() => effect(instance), []);
@@ -1493,29 +1490,18 @@ class MVC extends Model {
1493
1490
  effect(undefined);
1494
1491
  }
1495
1492
  }
1496
- if (typeof arg1 === "string")
1497
- return instance[arg1];
1498
- if (typeof arg1 === "function" && instance)
1499
- callback(arg1);
1500
- else if (arg2)
1501
- callback(arg2);
1502
- return instance;
1503
1493
  }
1504
1494
  static tap(arg1, arg2) {
1505
- const instance = this.get();
1506
- return typeof arg1 == "function"
1507
- ? useCompute(instance, arg1, arg2)
1508
- : useSubscribe(instance, arg1, arg2);
1495
+ return useTap(this, arg1, arg2);
1509
1496
  }
1510
1497
  static use(a, b) {
1511
- return useNew(this, a, b);
1498
+ return useModel(this, a, b);
1512
1499
  }
1513
1500
  static meta(arg1, arg2) {
1514
- return typeof arg1 == "function"
1515
- ? useCompute(this, arg1, arg2)
1516
- : useSubscribe(this, arg1, arg2);
1501
+ return useTap(() => this, arg1, arg2);
1517
1502
  }
1518
- }
1503
+ }
1504
+ FindInstruction.set(MVC, getContextForGetInstruction);
1519
1505
 
1520
1506
  const Oops$1 = issues({
1521
1507
  BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
@@ -1549,8 +1535,17 @@ function useNewContext(include, assign) {
1549
1535
  throw Oops.NoType();
1550
1536
  return ambient.push();
1551
1537
  }, []);
1552
- function register(key, T) {
1553
- const instance = context.has(key, T, i => init.add(i));
1538
+ function register(key, input) {
1539
+ let instance;
1540
+ if (MVC.isTypeof(input) && input.global)
1541
+ instance = input.new();
1542
+ else if (context.register.get(key) === input)
1543
+ instance = typeof input == "object"
1544
+ ? input
1545
+ : context.get(input);
1546
+ else
1547
+ instance = context.add(input, key);
1548
+ init.add(instance);
1554
1549
  if (assign)
1555
1550
  assignWeak(instance, assign);
1556
1551
  }
@@ -1622,12 +1617,7 @@ exports.Provider = Provider;
1622
1617
  exports.add = add;
1623
1618
  exports["default"] = MVC;
1624
1619
  exports.get = get;
1625
- exports.has = has;
1626
1620
  exports.ref = ref;
1627
1621
  exports.run = run;
1628
1622
  exports.set = set;
1629
- exports.tap = tap;
1630
- exports.use = use$1;
1631
- exports.useContext = useContext;
1632
- exports.useNew = useNew;
1633
- exports.useTap = useTap;
1623
+ exports.use = use;