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