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

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
@@ -2,7 +2,38 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var react = require('react');
5
+ var React = require('react');
6
+
7
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
+
11
+ /*! *****************************************************************************
12
+ Copyright (c) Microsoft Corporation.
13
+
14
+ Permission to use, copy, modify, and/or distribute this software for any
15
+ purpose with or without fee is hereby granted.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
+ PERFORMANCE OF THIS SOFTWARE.
24
+ ***************************************************************************** */
25
+
26
+ function __rest(s, e) {
27
+ var t = {};
28
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
29
+ t[p] = s[p];
30
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
31
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
32
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
33
+ t[p[i]] = s[p[i]];
34
+ }
35
+ return t;
36
+ }
6
37
 
7
38
  class Issue extends Error {
8
39
  constructor() {
@@ -13,9 +44,6 @@ class Issue extends Error {
13
44
  warn() {
14
45
  console.warn(this.message);
15
46
  }
16
- throw() {
17
- throw this;
18
- }
19
47
  }
20
48
  function issues(register) {
21
49
  const Library = {};
@@ -24,10 +52,10 @@ function issues(register) {
24
52
  return Library;
25
53
  }
26
54
 
27
- const Oops$8 = issues({
55
+ const Oops$9 = issues({
28
56
  BadEffectCallback: () => `Callback for effect-callback may only return a function.`
29
57
  });
30
- const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys: keys$1, values } = Object;
58
+ const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys, values } = Object;
31
59
  function define(target, key, value) {
32
60
  defineProperty(target, key, { value });
33
61
  }
@@ -53,7 +81,7 @@ function createEffect(callback) {
53
81
  if (unSet instanceof Promise)
54
82
  unSet = undefined;
55
83
  if (unSet && typeof unSet !== "function")
56
- throw Oops$8.BadEffectCallback();
84
+ throw Oops$9.BadEffectCallback();
57
85
  };
58
86
  }
59
87
  function createValueEffect(callback) {
@@ -61,7 +89,7 @@ function createValueEffect(callback) {
61
89
  return function (value) {
62
90
  if (typeof unSet == "function")
63
91
  unSet(value);
64
- const out = callback.call(this, value);
92
+ const out = callback.call(this, value, this);
65
93
  if (typeof out == "boolean")
66
94
  return out;
67
95
  if (!out || out instanceof Promise)
@@ -69,95 +97,182 @@ function createValueEffect(callback) {
69
97
  if (typeof out == "function")
70
98
  unSet = out;
71
99
  else
72
- throw Oops$8.BadEffectCallback();
100
+ throw Oops$9.BadEffectCallback();
73
101
  };
74
- }
75
- function select(source, select) {
76
- const proxy = {};
77
- for (const k in source)
78
- proxy[k] = k;
79
- return select(proxy);
80
- }
81
- function selectRecursive(using, keys) {
82
- const found = new Set();
83
- const spy = {};
84
- for (const key of new Set(keys))
85
- defineProperty(spy, key, {
86
- get() {
87
- found.add(key);
88
- return spy;
102
+ }
103
+
104
+ const Oops$8 = issues({
105
+ StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
106
+ NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
107
+ });
108
+ class Controller {
109
+ constructor(subject) {
110
+ this.subject = subject;
111
+ this.frame = new Set();
112
+ this.waiting = new Set();
113
+ this.followers = new Set();
114
+ }
115
+ start() {
116
+ this.state = {};
117
+ for (const key in this.subject)
118
+ this.manage(key);
119
+ const handle = new Set(this.waiting);
120
+ this.waiting.clear();
121
+ handle.forEach(cb => cb([]));
122
+ return this;
123
+ }
124
+ manage(key, handler) {
125
+ const { state, subject } = this;
126
+ const desc = getOwnPropertyDescriptor(subject, key);
127
+ if (desc && "value" in desc) {
128
+ const { value } = desc;
129
+ const instruction = Pending.get(value);
130
+ if (instruction) {
131
+ Pending.delete(value);
132
+ delete subject[key];
133
+ instruction.call(this, key, this);
89
134
  }
90
- });
91
- using(spy);
92
- return Array.from(found);
135
+ else if (typeof value !== "function" || /^[A-Z]/.test(key)) {
136
+ state[key] = value;
137
+ defineProperty(subject, key, {
138
+ enumerable: true,
139
+ get: () => state[key],
140
+ set: this.setter(key, handler)
141
+ });
142
+ }
143
+ }
144
+ }
145
+ setter(key, handler) {
146
+ const { state, subject } = this;
147
+ return (value) => {
148
+ if (state[key] == value)
149
+ return;
150
+ if (handler)
151
+ switch (handler.call(subject, value, state)) {
152
+ case true:
153
+ this.update(key);
154
+ case false:
155
+ return;
156
+ }
157
+ this.update(key, value);
158
+ };
159
+ }
160
+ addListener(listener) {
161
+ this.followers.add(listener);
162
+ return () => {
163
+ this.followers.delete(listener);
164
+ };
165
+ }
166
+ update(key, value) {
167
+ if (1 in arguments)
168
+ this.state[key] = value;
169
+ if (this.frame.has(key))
170
+ return;
171
+ if (!this.frame.size)
172
+ setTimeout(() => {
173
+ flush(this);
174
+ const keys = Object.freeze([...this.frame]);
175
+ const handle = new Set(this.waiting);
176
+ this.waiting.clear();
177
+ this.frame.clear();
178
+ UPDATE.set(this.subject, keys);
179
+ setImmediate(() => {
180
+ UPDATE.delete(this.subject);
181
+ });
182
+ handle.forEach(callback => {
183
+ try {
184
+ callback(keys);
185
+ }
186
+ catch (e) { }
187
+ });
188
+ }, 0);
189
+ this.frame.add(key);
190
+ for (const callback of this.followers) {
191
+ const event = callback(key, this);
192
+ if (typeof event == "function")
193
+ this.waiting.add(event);
194
+ }
195
+ }
196
+ requestUpdate(arg) {
197
+ if (typeof arg == "function") {
198
+ this.waiting.add(arg);
199
+ return;
200
+ }
201
+ if (typeof arg == "boolean" && arg !== this.frame.size > 0)
202
+ return Promise.reject(Oops$8.StrictUpdate(arg));
203
+ return {
204
+ then: (callback) => {
205
+ if (callback)
206
+ if (this.frame.size)
207
+ this.waiting.add(callback);
208
+ else
209
+ callback(false);
210
+ else
211
+ throw Oops$8.NoChaining();
212
+ }
213
+ };
214
+ }
93
215
  }
94
216
 
95
217
  class Subscriber {
96
218
  constructor(parent, onUpdate) {
97
219
  this.onUpdate = onUpdate;
98
220
  this.active = false;
99
- this.handle = {};
221
+ this.watch = {};
100
222
  this.dependant = new Set();
101
- this.listen = (key, from) => {
102
- const handler = this.handle[key];
103
- if (!handler)
104
- return;
105
- if (typeof handler == "function")
106
- handler();
107
- const notify = this.onUpdate(key, from);
108
- if (notify)
109
- from.waiting.add(notify);
110
- };
111
223
  if (!(parent instanceof Controller))
112
- parent = manage(parent);
113
- const subject = this.source =
114
- parent.subject;
115
- const proxy = this.proxy =
116
- create(subject);
224
+ parent = getController(parent);
117
225
  this.parent = parent;
118
- define(this.proxy, LOCAL, this);
119
- defineProperty(this.proxy, UPDATE, {
120
- get: () => (this.parent.handled.filter(key => key in this.handle))
226
+ this.source = parent.subject;
227
+ const proxy = this.proxy = create(parent.subject);
228
+ const DEBUG = (keys) => {
229
+ UPDATE.set(proxy, keys.filter(k => k in this.watch));
230
+ };
231
+ define(proxy, LOCAL, this);
232
+ defineProperty(this, "proxy", {
233
+ get: () => {
234
+ if (UPDATE.has(proxy))
235
+ setImmediate(() => {
236
+ UPDATE.delete(proxy);
237
+ });
238
+ return proxy;
239
+ }
121
240
  });
122
- if ("update" in subject) {
123
- define(proxy, "update", (...args) => {
124
- if (!args.length) {
125
- const refresh = this.onUpdate("", parent);
126
- if (refresh)
127
- refresh([]);
128
- }
129
- return subject.update(...args);
241
+ for (const key in parent.state) {
242
+ const existing = getOwnPropertyDescriptor(parent.subject, key);
243
+ const isUsing = () => {
244
+ this.watch[key] = true;
245
+ delete proxy[key];
246
+ return proxy[key];
247
+ };
248
+ setAlias(isUsing, `tap ${key}`);
249
+ defineProperty(proxy, key, {
250
+ set: existing.set,
251
+ get: isUsing,
252
+ configurable: true,
253
+ enumerable: true
130
254
  });
131
255
  }
132
- for (const key in parent.state)
133
- this.spy(key);
134
- }
135
- spy(key) {
136
- const { proxy, source } = this;
137
- const { set } = getOwnPropertyDescriptor(source, key);
138
- const intercept = () => {
139
- this.follow(key);
140
- delete proxy[key];
141
- return proxy[key];
142
- };
143
- setAlias(intercept, `tap ${key}`);
144
- defineProperty(proxy, key, {
145
- get: intercept,
146
- set,
147
- configurable: true,
148
- enumerable: true
149
- });
150
- }
151
- follow(key, callback) {
152
- this.handle[key] = callback || true;
153
- }
154
- commit() {
155
- const onDone = this.parent.addListener(this.listen);
156
- this.active = true;
157
- this.dependant.forEach(x => x.commit());
158
- return this.release = () => {
159
- this.dependant.forEach(x => x.release());
160
- onDone();
256
+ this.commit = () => {
257
+ const { parent } = this;
258
+ const onDone = parent.addListener(key => {
259
+ const handler = this.watch[key];
260
+ if (!handler)
261
+ return;
262
+ if (typeof handler == "function")
263
+ handler();
264
+ const notify = this.onUpdate(key, parent);
265
+ if (notify) {
266
+ parent.requestUpdate(DEBUG);
267
+ parent.requestUpdate(notify);
268
+ }
269
+ });
270
+ this.active = true;
271
+ this.dependant.forEach(x => x.commit());
272
+ return this.release = () => {
273
+ this.dependant.forEach(x => x.release());
274
+ onDone();
275
+ };
161
276
  };
162
277
  }
163
278
  }
@@ -181,7 +296,7 @@ function prepare(parent, key, source, setter, getter) {
181
296
  }
182
297
  register.set(key, info);
183
298
  const current = getter
184
- ? () => getter.call(subject, state[key], key)
299
+ ? () => getter(parent, key)
185
300
  : () => state[key];
186
301
  function compute(initial) {
187
302
  try {
@@ -239,7 +354,7 @@ function prepare(parent, key, source, setter, getter) {
239
354
  }
240
355
  finally {
241
356
  sub.commit();
242
- for (const key in sub.handle) {
357
+ for (const key in sub.watch) {
243
358
  const peer = register.get(key);
244
359
  if (peer && peer.priority >= info.priority)
245
360
  info.priority = peer.priority + 1;
@@ -259,7 +374,7 @@ function prepare(parent, key, source, setter, getter) {
259
374
  enumerable: true
260
375
  });
261
376
  }
262
- function ensure(on, keys) {
377
+ function ensure$1(on, keys) {
263
378
  for (const key of keys) {
264
379
  const desc = getOwnPropertyDescriptor(on.subject, key);
265
380
  const getter = desc && desc.get;
@@ -282,6 +397,287 @@ function flush(on) {
282
397
  KEYS.delete(on);
283
398
  }
284
399
 
400
+ const CONTROL = Symbol("CONTROL");
401
+ const WHY = Symbol("UPDATE");
402
+ const LOCAL = Symbol("LOCAL");
403
+ const STATE = Symbol("STATE");
404
+ const UPDATE = new WeakMap();
405
+ function ensure(subject, callback) {
406
+ const control = subject[CONTROL];
407
+ if (!control.state) {
408
+ let done;
409
+ control.requestUpdate(() => {
410
+ done = callback(control);
411
+ });
412
+ return () => done();
413
+ }
414
+ return callback(control);
415
+ }
416
+ function getController(subject) {
417
+ const control = subject[CONTROL];
418
+ if (!control.state)
419
+ control.start();
420
+ if (subject.didCreate)
421
+ subject.didCreate();
422
+ return control;
423
+ }
424
+ class Model {
425
+ constructor() {
426
+ define(this, CONTROL, new Controller(this));
427
+ define(this, "get", this);
428
+ define(this, "set", this);
429
+ }
430
+ get [STATE]() {
431
+ return this[CONTROL].state;
432
+ }
433
+ get [WHY]() {
434
+ return UPDATE.get(this);
435
+ }
436
+ on(select, handler, squash, once) {
437
+ return ensure(this, control => {
438
+ const keys = typeof select == "string" ? [select] :
439
+ !select.length ? getOwnPropertyNames(control.state) :
440
+ select;
441
+ ensure$1(control, keys);
442
+ const callback = squash
443
+ ? handler.bind(this)
444
+ : frame => frame
445
+ .filter(k => keys.includes(k))
446
+ .forEach(k => handler.call(this, control.state[k], k));
447
+ const trigger = once
448
+ ? frame => { remove(); callback(frame); }
449
+ : callback;
450
+ const remove = control.addListener(key => {
451
+ if (keys.includes(key))
452
+ return trigger;
453
+ });
454
+ return remove;
455
+ });
456
+ }
457
+ once(select, callback, squash) {
458
+ if (callback)
459
+ return this.on(select, callback, squash, true);
460
+ return new Promise(resolve => {
461
+ this.on(select, resolve, true, true);
462
+ });
463
+ }
464
+ effect(callback, select) {
465
+ const effect = createEffect(callback);
466
+ return ensure(this, control => {
467
+ if (!select) {
468
+ const sub = new Subscriber(control, () => invoke);
469
+ const invoke = () => {
470
+ const x = sub.proxy;
471
+ effect.call(x, x);
472
+ };
473
+ invoke();
474
+ return sub.commit();
475
+ }
476
+ const invoke = () => {
477
+ effect.call(this.get, this.get);
478
+ };
479
+ invoke();
480
+ if (!select.length)
481
+ select.push("willDestroy");
482
+ return control.addListener(key => {
483
+ if (select.includes(key))
484
+ return invoke;
485
+ });
486
+ });
487
+ }
488
+ import(from, subset) {
489
+ for (const key of subset || getOwnPropertyNames(this))
490
+ if (key in from)
491
+ this[key] = from[key];
492
+ }
493
+ export(subset) {
494
+ const { state } = getController(this);
495
+ const output = {};
496
+ for (const key of subset || getOwnPropertyNames(state))
497
+ output[key] = state[key];
498
+ return output;
499
+ }
500
+ update(arg, tag) {
501
+ const control = getController(this);
502
+ if (typeof arg == "string") {
503
+ control.update(arg);
504
+ if (1 in arguments && arg in this) {
505
+ const method = this[arg];
506
+ if (typeof method == "function")
507
+ if (typeof tag != "boolean")
508
+ method.call(this, tag);
509
+ else if (tag)
510
+ method.call(this);
511
+ }
512
+ arg = undefined;
513
+ }
514
+ return control.requestUpdate(arg);
515
+ }
516
+ destroy() {
517
+ this.update("willDestroy", true);
518
+ }
519
+ toString() {
520
+ return this.constructor.name;
521
+ }
522
+ static create(...args) {
523
+ const instance = new this(...args);
524
+ getController(instance);
525
+ return instance;
526
+ }
527
+ static isTypeof(maybe) {
528
+ return (typeof maybe == "function" &&
529
+ maybe.prototype instanceof this);
530
+ }
531
+ }
532
+ Model.CONTROL = CONTROL;
533
+ Model.STATE = STATE;
534
+ Model.LOCAL = LOCAL;
535
+ Model.WHY = WHY;
536
+ defineLazy(Model, CONTROL, function () {
537
+ return new Controller(this);
538
+ });
539
+
540
+ const Pending = new Map();
541
+ function apply(fn, label) {
542
+ const name = label || fn.name || "pending";
543
+ const placeholder = Symbol(`${name} instruction`);
544
+ function setup(key) {
545
+ const { subject, state } = this;
546
+ let output = fn.call(this, key, this);
547
+ let desc = {};
548
+ let get;
549
+ let set;
550
+ if (!output)
551
+ return;
552
+ if (typeof output == "function")
553
+ get = output;
554
+ else {
555
+ (({ get, set } = output), desc = __rest(output, ["get", "set"]));
556
+ if ("value" in desc) {
557
+ state[key] = desc.value;
558
+ if (get || set)
559
+ delete desc.value;
560
+ else {
561
+ defineProperty(subject, key, desc);
562
+ return;
563
+ }
564
+ }
565
+ }
566
+ defineProperty(subject, key, Object.assign(Object.assign({}, desc), { set: this.setter(key, set), get: get
567
+ ? function () {
568
+ return get(state[key], this[LOCAL]);
569
+ }
570
+ : () => state[key] }));
571
+ }
572
+ Pending.set(placeholder, setup);
573
+ return placeholder;
574
+ }
575
+
576
+ //TODO: sync instruction
577
+ function child(source, name) {
578
+ return apply(function child(key) {
579
+ const context = new WeakMap();
580
+ const peer = source.call(this, key);
581
+ function subscribe(sub) {
582
+ let child;
583
+ function init() {
584
+ if (child) {
585
+ child.release();
586
+ sub.dependant.delete(child);
587
+ context.set(sub, undefined);
588
+ child = undefined;
589
+ }
590
+ const instance = peer.get();
591
+ if (instance) {
592
+ child = new Subscriber(instance, sub.onUpdate);
593
+ if (sub.active)
594
+ child.commit();
595
+ sub.dependant.add(child);
596
+ context.set(sub, child.proxy);
597
+ }
598
+ }
599
+ init();
600
+ sub.watch[key] = init;
601
+ }
602
+ return {
603
+ value: peer.get(),
604
+ set: peer.set,
605
+ get(_value, local) {
606
+ if (!local)
607
+ return peer.get();
608
+ if (!context.has(local))
609
+ subscribe(local);
610
+ return context.get(local);
611
+ }
612
+ };
613
+ }, name || source.name);
614
+ }
615
+
616
+ const Parent = new WeakMap();
617
+ const Oops$6 = issues({
618
+ ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
619
+ UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
620
+ BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
621
+ });
622
+ function bootstrap(object) {
623
+ const breakdown = getOwnPropertyDescriptors(object);
624
+ const control = new Model();
625
+ for (const key in breakdown)
626
+ defineProperty(control, key, breakdown[key]);
627
+ return control;
628
+ }
629
+ function use$1(input, argument) {
630
+ return child(function use(key) {
631
+ const { subject } = this;
632
+ let current;
633
+ const onUpdate = (next) => {
634
+ if (next) {
635
+ current = next instanceof Model
636
+ ? next : bootstrap(next);
637
+ Parent.set(current, subject);
638
+ getController(current);
639
+ }
640
+ else
641
+ current = undefined;
642
+ if (typeof argument == "function")
643
+ return argument(current);
644
+ };
645
+ if (input) {
646
+ const initial = Model.isTypeof(input)
647
+ ? new input() :
648
+ input instanceof Model
649
+ ? input :
650
+ typeof input === "function"
651
+ ? input() :
652
+ typeof input === "object"
653
+ ? bootstrap(input)
654
+ : null;
655
+ if (initial)
656
+ onUpdate(initial);
657
+ else if (initial === null)
658
+ throw Oops$6.BadArgument(typeof input);
659
+ }
660
+ return {
661
+ get: () => current,
662
+ set: onUpdate
663
+ };
664
+ });
665
+ }
666
+ function parent(Expects, required) {
667
+ return apply(function parent() {
668
+ const child = this.subject;
669
+ const expected = Expects.name;
670
+ const value = Parent.get(this.subject);
671
+ if (!value) {
672
+ if (required)
673
+ throw Oops$6.ParentRequired(expected, child);
674
+ }
675
+ else if (!(value instanceof Expects))
676
+ throw Oops$6.UnexpectedParent(expected, child, value);
677
+ return { value };
678
+ });
679
+ }
680
+
285
681
  const Lifecycle = {
286
682
  WILL_RENDER: "willRender",
287
683
  WILL_UPDATE: "willUpdate",
@@ -289,7 +685,7 @@ const Lifecycle = {
289
685
  WILL_UNMOUNT: "willUnmount",
290
686
  DID_MOUNT: "didMount"
291
687
  };
292
- const lifecycleEvents = [
688
+ [
293
689
  "didCreate",
294
690
  "willDestroy",
295
691
  ...values(Lifecycle)
@@ -297,7 +693,7 @@ const lifecycleEvents = [
297
693
  function lifecycle(prefix) {
298
694
  const type = eventsFor(prefix);
299
695
  return function useLifecycle(sub, tag) {
300
- const emit = react.useMemo(() => {
696
+ const emit = React__default["default"].useMemo(() => {
301
697
  const subject = sub.source;
302
698
  const id = typeof tag == "function" ? tag(subject) : tag;
303
699
  return (name) => {
@@ -309,7 +705,7 @@ function lifecycle(prefix) {
309
705
  emit(sub.active
310
706
  ? Lifecycle.WILL_UPDATE
311
707
  : Lifecycle.WILL_MOUNT);
312
- react.useLayoutEffect(() => {
708
+ React__default["default"].useLayoutEffect(() => {
313
709
  sub.commit();
314
710
  emit(Lifecycle.DID_MOUNT);
315
711
  return () => {
@@ -323,210 +719,264 @@ function eventsFor(prefix) {
323
719
  const map = new Map();
324
720
  for (const name of values(Lifecycle)) {
325
721
  const alias = prefix + name[0].toUpperCase() + name.slice(1);
326
- lifecycleEvents.push(alias);
327
722
  map.set(name, alias);
328
723
  }
329
724
  return (e) => map.get(e);
330
725
  }
331
726
 
332
- const CONTROL = Symbol("control");
333
- const UPDATE = Symbol("update");
334
- const LOCAL = Symbol("local");
335
- const STATE = Symbol("state");
336
- function manage(src) {
337
- return src[CONTROL];
727
+ const useElementLifecycle = lifecycle("element");
728
+ const useComponentLifecycle = lifecycle("component");
729
+ function use(init) {
730
+ const [state, update] = React__default["default"].useState(() => [
731
+ init(() => update(state.concat()))
732
+ ]);
733
+ return state[0];
338
734
  }
339
- const Pending = new Map();
340
- function apply(fn, label) {
341
- const name = label || fn.name || "pending";
342
- const placeholder = Symbol(`${name} instruction`);
343
- function setup(key) {
344
- let output = fn.call(this, key, this);
345
- if (typeof output == "function") {
346
- const getter = output;
347
- output = Object.assign(Object.assign({}, getOwnPropertyDescriptor(this.subject, key)), { get() {
348
- return getter(this[LOCAL]);
349
- } });
735
+ function useTap(model, path, expect) {
736
+ if (typeof path == "function")
737
+ return useComputed(model, path, expect);
738
+ const proxy = useActive(model, path, expect);
739
+ model.update("willRender", true);
740
+ return proxy;
741
+ }
742
+ function useTag(model, id) {
743
+ const hook = use(refresh => (new Subscriber(model, () => refresh)));
744
+ useElementLifecycle(hook, id || 0);
745
+ return hook.proxy;
746
+ }
747
+ function useNew(model, callback) {
748
+ const hook = use(refresh => {
749
+ if (callback)
750
+ callback(model);
751
+ return new Subscriber(model, () => refresh);
752
+ });
753
+ useComponentLifecycle(hook);
754
+ return hook.proxy;
755
+ }
756
+ function usePassive(Type, callback) {
757
+ const instance = React__default["default"].useMemo(() => {
758
+ const instance = Type.create();
759
+ if (callback)
760
+ callback(instance);
761
+ return instance;
762
+ }, []);
763
+ React__default["default"].useLayoutEffect(() => () => instance.destroy(), []);
764
+ instance.update("willRender", true);
765
+ return instance;
766
+ }
767
+ function useActive(target, focus, expected) {
768
+ const hook = use(refresh => {
769
+ const sub = new Subscriber(target, () => refresh);
770
+ if (focus) {
771
+ const source = sub.proxy;
772
+ defineProperty(sub, "proxy", {
773
+ get() {
774
+ const value = source[focus];
775
+ if (value === undefined && expected)
776
+ throw suspend(sub.parent, focus);
777
+ return value;
778
+ }
779
+ });
350
780
  }
351
- if (output)
352
- defineProperty(this.subject, key, output);
353
- }
354
- Pending.set(placeholder, setup);
355
- return placeholder;
781
+ return sub;
782
+ });
783
+ React__default["default"].useLayoutEffect(() => hook.commit(), []);
784
+ return hook.proxy;
356
785
  }
357
- class Controller {
358
- constructor(subject) {
359
- this.subject = subject;
360
- this.state = {};
361
- this.frame = new Set();
362
- this.waiting = new Set();
363
- this.handled = [];
364
- this.followers = new Set();
365
- }
366
- static setup(onto) {
367
- const control = new this(onto);
368
- defineProperty(onto, CONTROL, {
369
- configurable: true,
370
- get() {
371
- defineProperty(onto, CONTROL, {
372
- value: control
373
- });
374
- defineProperty(onto, STATE, {
375
- get: () => (Object.assign({}, control.state)),
376
- configurable: true
377
- });
378
- defineProperty(onto, UPDATE, {
379
- get: () => [...control.handled],
380
- configurable: true
381
- });
382
- control.start();
383
- if (onto.didCreate)
384
- onto.didCreate();
385
- return control;
786
+ function useComputed(target, compute, expected) {
787
+ const hook = use(refresh => {
788
+ const sub = new Subscriber(target, () => update);
789
+ const spy = sub.proxy;
790
+ let value = compute.call(spy, spy);
791
+ let update;
792
+ let retry;
793
+ const set = (next) => {
794
+ value = next;
795
+ if (retry) {
796
+ retry();
797
+ retry = undefined;
798
+ }
799
+ else
800
+ refresh();
801
+ };
802
+ if (value instanceof Promise) {
803
+ value.then(set);
804
+ value = undefined;
805
+ }
806
+ else {
807
+ sub.commit();
808
+ update = () => {
809
+ const next = compute.call(spy, spy);
810
+ if (value != next)
811
+ set(next);
812
+ };
813
+ }
814
+ const get = expected
815
+ ? () => {
816
+ if (value === undefined)
817
+ throw new Promise(res => retry = res);
818
+ return value;
386
819
  }
820
+ : () => value;
821
+ defineProperty(sub, "proxy", { get });
822
+ return sub;
823
+ });
824
+ React__default["default"].useLayoutEffect(() => hook.release, []);
825
+ return hook.proxy;
826
+ }
827
+ function useModel(Type, callback) {
828
+ const hook = use(refresh => {
829
+ const instance = new Type();
830
+ const sub = new Subscriber(instance, () => refresh);
831
+ const release = sub.parent.addListener((key) => {
832
+ if (key == Lifecycle.WILL_UNMOUNT)
833
+ return () => {
834
+ instance.destroy();
835
+ release();
836
+ };
387
837
  });
388
- return control;
838
+ if (callback)
839
+ callback(instance);
840
+ return sub;
841
+ });
842
+ useComponentLifecycle(hook);
843
+ usePeerContext(hook.source);
844
+ return hook.proxy;
845
+ }
846
+
847
+ class Lookup {
848
+ constructor() {
849
+ this.table = new Map();
389
850
  }
390
- get pending() {
391
- return this.frame.size > 0;
851
+ get local() {
852
+ return [
853
+ ...new Set(getOwnPropertySymbols(this).map(symbol => this[symbol]))
854
+ ];
392
855
  }
393
- start() {
394
- const { subject } = this;
395
- for (const key in subject) {
396
- const desc = getOwnPropertyDescriptor(subject, key);
397
- if (desc && "value" in desc) {
398
- const { value } = desc;
399
- const instruction = Pending.get(value);
400
- if (instruction) {
401
- Pending.delete(value);
402
- delete subject[key];
403
- instruction.call(this, key, this);
404
- }
405
- else if (typeof value !== "function" || /^[A-Z]/.test(key))
406
- this.manage(key, value);
407
- }
856
+ key(T) {
857
+ let key = this.table.get(T);
858
+ if (!key) {
859
+ key = Symbol(T.name);
860
+ this.table.set(T, key);
408
861
  }
409
- this.emit();
410
- return this;
411
- }
412
- select(using) {
413
- const keys = getOwnPropertyNames(this.state);
414
- return using
415
- ? selectRecursive(using, keys.concat(lifecycleEvents))
416
- : keys;
417
- }
418
- manage(key, initial, effect) {
419
- const { state, subject } = this;
420
- state[key] = initial;
421
- defineProperty(subject, key, {
422
- enumerable: true,
423
- configurable: true,
424
- get: () => state[key],
425
- set: this.setter(key, effect)
426
- });
862
+ return key;
427
863
  }
428
- setter(key, handler) {
429
- const { state, subject } = this;
430
- return (value) => {
431
- if (state[key] == value)
432
- return;
433
- if (handler)
434
- switch (handler.call(subject, value)) {
435
- case true:
436
- this.update(key);
437
- case false:
438
- return;
439
- }
440
- this.update(key, value);
441
- };
864
+ get(T) {
865
+ return this[this.key(T)];
442
866
  }
443
- addListener(listener) {
444
- this.followers.add(listener);
445
- return () => {
446
- this.followers.delete(listener);
447
- };
867
+ push(I) {
868
+ const next = create(this);
869
+ if (I instanceof Model || typeof I == "function")
870
+ next.register(I);
871
+ else
872
+ for (const i of values(I))
873
+ next.register(i);
874
+ return next;
448
875
  }
449
- update(key, value) {
450
- if (1 in arguments)
451
- this.state[key] = value;
452
- if (this.frame.has(key))
453
- return;
454
- if (!this.frame.size)
455
- setTimeout(() => this.emit(), 0);
456
- this.frame.add(key);
457
- for (const subscription of this.followers) {
458
- const notify = subscription(key, this);
459
- if (notify)
460
- this.waiting.add(notify);
876
+ register(I) {
877
+ let writable = true;
878
+ let T;
879
+ if (I instanceof Model) {
880
+ T = I.constructor;
881
+ writable = false;
461
882
  }
883
+ else {
884
+ T = I;
885
+ I = I.create();
886
+ }
887
+ do {
888
+ const key = this.key(T);
889
+ const conflict = this.hasOwnProperty(key);
890
+ defineProperty(this, key, {
891
+ value: conflict ? null : I,
892
+ configurable: true,
893
+ writable
894
+ });
895
+ T = getPrototypeOf(T);
896
+ } while (T !== Model);
897
+ return I;
462
898
  }
463
- emit() {
464
- flush(this);
465
- const handle = new Set(this.waiting);
466
- const handled = this.handled =
467
- Object.freeze([...this.frame]);
468
- this.waiting.clear();
469
- this.frame.clear();
470
- handle.forEach(callback => {
471
- try {
472
- callback(handled);
473
- }
474
- catch (e) { }
475
- });
476
- }
477
- }
478
- function keys(from, using) {
479
- if (typeof using == "string")
480
- return [using];
481
- if (typeof using == "object") {
482
- using = Array.from(using);
483
- if (using.length === 0)
484
- using = undefined;
485
- else
486
- return using;
899
+ pop() {
900
+ for (const key of getOwnPropertySymbols(this)) {
901
+ const entry = getOwnPropertyDescriptor(this, key);
902
+ if (entry.writable)
903
+ entry.value.destroy();
904
+ }
487
905
  }
488
- return from.select(using);
489
906
  }
490
907
 
491
- function child(source, name) {
492
- return apply(function child(key) {
493
- const context = new WeakMap();
494
- const current = source.call(this, key);
495
- function subscribe(sub) {
496
- let child;
497
- function start() {
498
- const instance = current();
499
- if (instance) {
500
- child = new Subscriber(instance, sub.onUpdate);
501
- if (sub.active)
502
- child.commit();
503
- sub.dependant.add(child);
504
- context.set(sub, child.proxy);
505
- }
506
- }
507
- function restart() {
508
- if (child) {
509
- child.release();
510
- sub.dependant.delete(child);
511
- context.set(sub, undefined);
512
- child = undefined;
513
- }
514
- start();
515
- }
516
- start();
517
- sub.follow(key, restart);
518
- }
519
- return (local) => {
520
- if (!local)
521
- return current();
522
- if (!context.has(local))
523
- subscribe(local);
524
- return context.get(local);
908
+ const Oops$5 = issues({
909
+ NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
910
+ NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
911
+ BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
912
+ });
913
+ const LookupContext = React__default["default"].createContext(new Lookup());
914
+ const useLookup = () => React__default["default"].useContext(LookupContext);
915
+ function useContext(Type, strict) {
916
+ const instance = useLookup().get(Type);
917
+ if (!instance && strict)
918
+ throw Oops$5.NothingInContext(Type.name);
919
+ return instance;
920
+ }
921
+ function Consumer(props) {
922
+ const { get, has, children, of: Control } = props;
923
+ if (typeof children == "function")
924
+ return children(useTap(useContext(Control)));
925
+ const callback = has || get;
926
+ if (typeof callback == "function")
927
+ callback(useContext(Control, !!has));
928
+ else
929
+ throw Oops$5.BadConsumerProps();
930
+ return null;
931
+ }
932
+ function useNewContext(inject) {
933
+ const from = useLookup();
934
+ return React__default["default"].useMemo(() => {
935
+ if (!inject)
936
+ throw Oops$5.NoProviderType();
937
+ const context = from.push(inject);
938
+ for (const instance of context.local)
939
+ if (instance)
940
+ for (const apply of getPending(instance))
941
+ apply(context);
942
+ return context;
943
+ }, []);
944
+ }
945
+ function useAppliedProps(within, props) {
946
+ const update = React__default["default"].useMemo(() => {
947
+ const targets = within.local;
948
+ return function integrate(props) {
949
+ for (const [key, value] of entries(props))
950
+ if (key != "of" && key != "children")
951
+ for (const into of targets)
952
+ if (into && key in into)
953
+ into[key] = value;
525
954
  };
526
- }, name || source.name);
955
+ }, []);
956
+ update(props);
957
+ }
958
+ function RenderFunction(props) {
959
+ const hook = use(refresh => {
960
+ const targets = props.context.local;
961
+ if (targets.length == 1)
962
+ return new Subscriber(targets[0], () => refresh);
963
+ return {};
964
+ });
965
+ if (hook.commit)
966
+ React__default["default"].useLayoutEffect(() => hook.commit(), []);
967
+ return props.render(hook.proxy);
968
+ }
969
+ function Provider(props) {
970
+ const context = useNewContext(props.of);
971
+ const render = props.children;
972
+ useAppliedProps(context, props);
973
+ React__default["default"].useLayoutEffect(() => () => context.pop(), []);
974
+ return React__default["default"].createElement(LookupContext.Provider, { value: context }, typeof render == "function"
975
+ ? React__default["default"].createElement(RenderFunction, { context, render })
976
+ : render);
527
977
  }
528
978
 
529
- const Oops$6 = issues({
979
+ const Oops$4 = issues({
530
980
  CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
531
981
  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.`
532
982
  });
@@ -534,14 +984,16 @@ const PendingContext = new WeakMap();
534
984
  const ContextWasUsed = new WeakMap();
535
985
  function tap(type, argument) {
536
986
  return child(function tap(key) {
537
- return pendingAccess(this.subject, type, key, argument);
987
+ return {
988
+ get: pendingAccess(this.subject, type, key, argument)
989
+ };
538
990
  });
539
991
  }
540
992
  function pendingAccess(from, type, key, argument) {
541
- if ("current" in type)
542
- return () => type.current;
543
- if ("current" in from.constructor)
544
- throw Oops$6.CantAttachGlobal(from, type.name);
993
+ if ("set" in type)
994
+ return () => type.get();
995
+ if ("set" in from.constructor)
996
+ throw Oops$4.CantAttachGlobal(from, type.name);
545
997
  let instance;
546
998
  getPending(from).push(context => {
547
999
  instance = context.get(type);
@@ -550,7 +1002,7 @@ function pendingAccess(from, type, key, argument) {
550
1002
  instance = undefined;
551
1003
  }
552
1004
  else if (!instance && argument)
553
- throw Oops$6.AmbientRequired(type.name, from, key);
1005
+ throw Oops$4.AmbientRequired(type.name, from, key);
554
1006
  });
555
1007
  return () => instance;
556
1008
  }
@@ -576,7 +1028,7 @@ function getPending(subject) {
576
1028
  return pending;
577
1029
  }
578
1030
 
579
- const Oops$5 = issues({
1031
+ const Oops$3 = issues({
580
1032
  DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
581
1033
  BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
582
1034
  PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
@@ -593,7 +1045,7 @@ function ref(arg) {
593
1045
  return apply(function ref(key) {
594
1046
  let value = {};
595
1047
  if (typeof arg == "object") {
596
- const source = manage(arg);
1048
+ const source = getController(arg);
597
1049
  for (const key in source.state)
598
1050
  defineLazy(value, key, createRef.bind(source, key));
599
1051
  }
@@ -607,7 +1059,7 @@ function act(task) {
607
1059
  let pending = false;
608
1060
  const invoke = (...args) => {
609
1061
  if (pending)
610
- return Promise.reject(Oops$5.DuplicateAction(key));
1062
+ return Promise.reject(Oops$3.DuplicateAction(key));
611
1063
  pending = true;
612
1064
  this.update(key);
613
1065
  return new Promise(res => {
@@ -628,16 +1080,19 @@ function act(task) {
628
1080
  };
629
1081
  });
630
1082
  }
631
- function from(source, setter, getter) {
1083
+ function from(source, setter, argument) {
632
1084
  return apply(function from(key) {
633
- const { subject } = this;
634
1085
  let getSource;
1086
+ const { subject } = this;
1087
+ const getter = argument === true
1088
+ ? pendingValue
1089
+ : argument || undefined;
635
1090
  // Easy mistake, using a peer, will always be unresolved.
636
1091
  if (typeof source == "symbol")
637
- throw Oops$5.PeerNotAllowed(subject, key);
1092
+ throw Oops$3.PeerNotAllowed(subject, key);
638
1093
  // replace source controller in-case different
639
1094
  if (typeof source == "object")
640
- getSource = () => manage(source);
1095
+ getSource = () => getController(source);
641
1096
  // specifically an arrow function (getter factory)
642
1097
  else if (!source.prototype) {
643
1098
  setter = source.call(subject, key);
@@ -646,22 +1101,24 @@ function from(source, setter, getter) {
646
1101
  // is a peer Model (constructor)
647
1102
  else if (Model.isTypeof(source))
648
1103
  getSource = pendingAccess(subject, source, key, true);
649
- // Regular function is to ambiguous so not allowed.
1104
+ // Regular function is too ambiguous so not allowed.
650
1105
  else
651
- throw Oops$5.BadComputedSource(subject, key, source);
1106
+ throw Oops$3.BadComputedSource(subject, key, source);
652
1107
  prepare(this, key, getSource, setter, getter);
653
1108
  });
654
1109
  }
655
1110
 
656
- const Oops$4 = issues({
1111
+ const Oops$2 = issues({
657
1112
  ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
658
1113
  });
1114
+ /* deprecated - ignore coverage */
1115
+ /* istanbul ignore next */
659
1116
  function pending(source, compute) {
660
- return (source === undefined ?
661
- suspendForValue() :
662
- typeof source == "function" && !source.prototype ?
663
- suspendForAsync(source) :
664
- suspendForComputed(source, compute));
1117
+ if (source === undefined)
1118
+ return set();
1119
+ if (typeof source == "function" && !source.prototype)
1120
+ return set(source);
1121
+ return from(source, compute, true);
665
1122
  }
666
1123
  /**
667
1124
  * Get value, suspend instead if undefined.
@@ -675,442 +1132,140 @@ function pendingValue(via, key) {
675
1132
  throw suspend(via, key);
676
1133
  return value;
677
1134
  }
678
- function suspend(source, key) {
679
- const error = Oops$4.ValueNotReady(source.subject, key);
680
- const promise = new Promise(resolve => {
681
- const release = source.addListener(forKey => {
682
- if (forKey == key)
683
- return () => {
684
- if (source.state[key] !== undefined) {
685
- release();
686
- resolve();
687
- }
688
- };
689
- });
690
- });
691
- return Object.assign(promise, {
692
- toString: () => String(error),
693
- name: "Suspense",
694
- message: error.message,
695
- stack: error.stack
696
- });
697
- }
698
- function suspendForComputed(source, compute) {
699
- function getter(_value, key) {
700
- return pendingValue(manage(this), key);
701
- }
702
- return from(source, compute, getter);
703
- }
704
- function suspendForValue() {
705
- return apply(function pending(key) {
706
- this.state[key] = undefined;
707
- return {
708
- set: this.setter(key),
709
- get: () => pendingValue(this, key)
710
- };
711
- });
712
- }
713
- function suspendForAsync(source) {
714
- return apply(function suspense(key) {
715
- const subject = this.subject;
716
- let waiting = true;
717
- let value;
718
- let error;
719
- return () => {
720
- if (error)
721
- throw error;
722
- if (!waiting)
723
- return value;
724
- const issue = Oops$4.ValueNotReady(subject, key);
725
- let suspend = source
726
- .call(subject, key)
1135
+ function pendingFactory(via, key, fn) {
1136
+ const { subject, state } = via;
1137
+ let waiting;
1138
+ let error;
1139
+ return () => {
1140
+ if (waiting)
1141
+ throw waiting;
1142
+ if (error)
1143
+ throw error;
1144
+ if (key in state)
1145
+ return state[key];
1146
+ let output;
1147
+ try {
1148
+ output = fn.call(subject, key, subject);
1149
+ }
1150
+ catch (err) {
1151
+ throw error = err;
1152
+ }
1153
+ if (output instanceof Promise) {
1154
+ const issue = Oops$2.ValueNotReady(subject, key);
1155
+ output
727
1156
  .catch(err => error = err)
728
- .then(out => value = out)
729
- .finally(() => waiting = false);
730
- throw Object.assign(suspend, {
1157
+ .then(out => state[key] = out)
1158
+ .finally(() => waiting = undefined);
1159
+ throw waiting = Object.assign(output, {
731
1160
  message: issue.message,
732
1161
  stack: issue.stack
733
1162
  });
734
- };
735
- });
736
- }
737
-
738
- function use$1(init) {
739
- const [state, update] = react.useState(() => [
740
- init(() => update(state.concat()))
741
- ]);
742
- return state[0];
743
- }
744
- function useLazy(Type, callback) {
745
- const instance = react.useMemo(() => {
746
- const instance = Type.create();
747
- if (callback)
748
- callback(instance);
749
- return instance;
750
- }, []);
751
- react.useLayoutEffect(() => () => instance.destroy(), []);
752
- return instance;
753
- }
754
- function useWatcher(target, focus, expected) {
755
- const hook = use$1(refresh => {
756
- const sub = new Subscriber(target, () => refresh);
757
- if (focus) {
758
- const source = sub.proxy;
759
- defineProperty(sub, "proxy", {
760
- get() {
761
- const value = source[focus];
762
- if (value === undefined && expected)
763
- throw suspend(sub.parent, focus);
764
- return value;
765
- }
766
- });
767
1163
  }
768
- return sub;
769
- });
770
- react.useLayoutEffect(() => hook.commit(), []);
771
- return hook.proxy;
772
- }
773
- function useComputed(target, compute, expected) {
774
- const hook = use$1(refresh => {
775
- const sub = new Subscriber(target, () => update);
776
- const { proxy } = sub;
777
- let value;
778
- let retry;
779
- const update = () => {
780
- const next = compute.call(proxy, proxy);
781
- if (value == next)
782
- return;
783
- value = next;
784
- if (retry) {
785
- retry();
786
- retry = undefined;
787
- }
788
- else
789
- refresh();
790
- };
791
- const access = () => {
792
- if (value === undefined && expected)
793
- throw new Promise(res => {
794
- retry = res;
795
- });
796
- return value;
797
- };
798
- value = compute.call(proxy, proxy);
799
- sub.commit();
800
- defineProperty(sub, "proxy", { get: access });
801
- return sub;
802
- });
803
- react.useLayoutEffect(() => hook.release, []);
804
- return hook.proxy;
1164
+ else {
1165
+ return state[key] = output;
1166
+ }
1167
+ };
805
1168
  }
806
- function useModel(Type, callback) {
807
- const hook = use$1(refresh => {
808
- const instance = new Type();
809
- const control = manage(instance);
810
- const sub = new Subscriber(control, () => refresh);
811
- const release = control.addListener((key) => {
812
- if (key == Lifecycle.WILL_UNMOUNT)
1169
+ function suspend(source, key) {
1170
+ const error = Oops$2.ValueNotReady(source.subject, key);
1171
+ const promise = new Promise(resolve => {
1172
+ const release = source.addListener(forKey => {
1173
+ if (forKey == key)
813
1174
  return () => {
814
- instance.destroy();
815
- release();
1175
+ if (source.state[key] !== undefined) {
1176
+ release();
1177
+ resolve();
1178
+ }
816
1179
  };
817
1180
  });
818
- if (callback)
819
- callback(instance);
820
- return sub;
821
1181
  });
822
- return hook.proxy;
823
- }
824
-
825
- class Lookup {
826
- constructor() {
827
- this.table = new Map();
828
- }
829
- get local() {
830
- return getOwnPropertySymbols(this).map((symbol) => this[symbol]);
831
- }
832
- key(T) {
833
- let key = this.table.get(T);
834
- if (!key) {
835
- key = Symbol(T.name);
836
- this.table.set(T, key);
837
- }
838
- return key;
839
- }
840
- get(T) {
841
- return this[this.key(T)];
842
- }
843
- push(I) {
844
- const next = create(this);
845
- if (I instanceof Model || typeof I == "function")
846
- next.register(I);
847
- else
848
- for (const i of values(I))
849
- next.register(i);
850
- return next;
851
- }
852
- register(I) {
853
- let writable = true;
854
- let T;
855
- if (I instanceof Model) {
856
- T = I.constructor;
857
- writable = false;
858
- }
859
- else {
860
- T = I;
861
- I = I.create();
862
- }
863
- do {
864
- defineProperty(this, this.key(T), {
865
- value: I, writable
866
- });
867
- T = getPrototypeOf(T);
868
- } while (T !== Model);
869
- return I;
870
- }
871
- pop() {
872
- for (const key of getOwnPropertySymbols(this)) {
873
- const entry = getOwnPropertyDescriptor(this, key);
874
- if (entry.writable)
875
- entry.value.destroy();
876
- }
877
- }
1182
+ return Object.assign(promise, {
1183
+ toString: () => String(error),
1184
+ name: "Suspense",
1185
+ message: error.message,
1186
+ stack: error.stack
1187
+ });
878
1188
  }
879
1189
 
880
- const Oops$3 = issues({
881
- NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
882
- NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
883
- BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
1190
+ const Oops$1 = issues({
1191
+ NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
1192
+ BadFactory: () => `Set instruction can only accept a factory or undefined.`,
1193
+ FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
884
1194
  });
885
- const LookupContext = react.createContext(new Lookup());
886
- const useLookup = () => react.useContext(LookupContext);
887
- function useFromContext(Type, strict) {
888
- const instance = useLookup().get(Type);
889
- if (!instance && strict)
890
- throw Oops$3.NothingInContext(Type.name);
891
- return instance;
892
- }
893
- function Consumer(props) {
894
- const { get, has, children, of: Control } = props;
895
- if (typeof children == "function")
896
- return children(Control.tap());
897
- const callback = has || get;
898
- if (typeof callback == "function")
899
- callback(Control.get(!!has));
900
- else
901
- throw Oops$3.BadConsumerProps();
902
- return null;
903
- }
904
- function useNewContext(from, inject) {
905
- return react.useMemo(() => {
906
- if (!inject)
907
- throw Oops$3.NoProviderType();
908
- const context = from.push(inject);
909
- for (const instance of context.local)
910
- for (const apply of getPending(instance))
911
- apply(context);
912
- return context;
913
- }, []);
914
- }
915
- function useAppliedProps(within, props) {
916
- const update = react.useMemo(() => {
917
- const targets = within.local;
918
- return function integrate(props) {
919
- for (const [key, value] of entries(props))
920
- if (key != "of" && key != "children")
921
- for (const into of targets)
922
- if (key in into)
923
- into[key] = value;
924
- };
925
- }, []);
926
- update(props);
1195
+ function lazy(value) {
1196
+ return apply(function lazy(key) {
1197
+ const source = this.subject;
1198
+ source[key] = value;
1199
+ defineProperty(this.state, key, {
1200
+ get: () => source[key]
1201
+ });
1202
+ });
927
1203
  }
928
- function RenderFunction(props) {
929
- const hook = use$1(refresh => {
930
- const targets = props.context.local;
931
- if (targets.length == 1)
932
- return new Subscriber(targets[0], () => refresh);
933
- return {};
1204
+ function set(factory, argument) {
1205
+ return apply(function set(key) {
1206
+ let set;
1207
+ let get;
1208
+ const required = argument === true || argument === undefined;
1209
+ if (factory === undefined)
1210
+ get = () => pendingValue(this, key);
1211
+ else if (typeof factory !== "function")
1212
+ throw Oops$1.BadFactory();
1213
+ else {
1214
+ get = pendingFactory(this, key, factory);
1215
+ if (required)
1216
+ try {
1217
+ get();
1218
+ }
1219
+ catch (err) {
1220
+ if (err instanceof Promise)
1221
+ ;
1222
+ else {
1223
+ Oops$1.FactoryFailed(this.subject, key).warn();
1224
+ throw err;
1225
+ }
1226
+ }
1227
+ }
1228
+ if (typeof argument == "function")
1229
+ set = createValueEffect(argument);
1230
+ else
1231
+ set = (value) => {
1232
+ if (value === undefined && required)
1233
+ throw Oops$1.NonOptional(this.subject, key);
1234
+ };
1235
+ return { set, get };
934
1236
  });
935
- if (hook.commit)
936
- react.useLayoutEffect(() => hook.commit(), []);
937
- return props.render(hook.proxy);
938
1237
  }
939
- function Provider(props) {
940
- const render = props.children;
941
- const current = useLookup();
942
- const context = useNewContext(current, props.of);
943
- useAppliedProps(context, props);
944
- react.useLayoutEffect(() => () => context.pop(), []);
945
- return react.createElement(LookupContext.Provider, { value: context }, typeof render == "function"
946
- ? react.createElement(RenderFunction, { context, render })
947
- : render);
1238
+ function on(initial, onUpdate) {
1239
+ return set(initial && (() => initial), onUpdate);
948
1240
  }
949
1241
 
950
- const Oops$2 = issues({
951
- StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
952
- NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
953
- });
954
- const useElementLifecycle = lifecycle("element");
955
- const useComponentLifecycle = lifecycle("component");
956
- class Model {
957
- constructor() {
958
- const control = Controller.setup(this);
959
- define(this, "get", this);
960
- define(this, "set", this);
961
- defer(control, "on");
962
- defer(control, "effect");
963
- control.waiting.add(() => {
964
- delete this.on;
965
- delete this.effect;
966
- });
967
- }
1242
+ class MVC extends Model {
968
1243
  tap(path, expect) {
969
- if (typeof path == "function")
970
- return useComputed(this, path, expect);
971
- const proxy = useWatcher(this, path, expect);
972
- this.update("willRender", true);
973
- return proxy;
1244
+ return useTap(this, path, expect);
974
1245
  }
975
1246
  tag(id) {
976
- const hook = use$1(refresh => {
977
- return new Subscriber(this, () => refresh);
978
- });
979
- useElementLifecycle(hook, id || 0);
980
- return hook.proxy;
1247
+ return useTag(this, id);
981
1248
  }
982
1249
  use(callback) {
983
- const hook = use$1(refresh => {
984
- if (callback)
985
- callback(this);
986
- return new Subscriber(this, () => refresh);
987
- });
988
- useComponentLifecycle(hook);
989
- return hook.proxy;
990
- }
991
- on(subset, handler, squash, once) {
992
- const control = manage(this);
993
- const request = keys(control, subset);
994
- const callback = squash
995
- ? handler.bind(this)
996
- : frame => frame
997
- .filter(k => request.includes(k))
998
- .forEach(k => handler.call(this, control.state[k], k));
999
- const trigger = once
1000
- ? frame => { remove(); callback(frame); }
1001
- : callback;
1002
- ensure(control, request);
1003
- const remove = control.addListener(key => {
1004
- if (request.includes(key))
1005
- return trigger;
1006
- });
1007
- return remove;
1008
- }
1009
- once(select, callback, squash) {
1010
- if (callback)
1011
- return this.on(select, callback, squash, true);
1012
- else
1013
- return new Promise(resolve => {
1014
- this.on(select, resolve, true, true);
1015
- });
1016
- }
1017
- effect(callback, select) {
1018
- const control = manage(this);
1019
- let target = this;
1020
- const effect = createEffect(callback);
1021
- const invoke = () => effect.call(target, target);
1022
- if (select) {
1023
- invoke();
1024
- return this.on(select, invoke, true);
1025
- }
1026
- else {
1027
- const sub = new Subscriber(control, () => invoke);
1028
- target = sub.proxy;
1029
- invoke();
1030
- return sub.commit();
1031
- }
1032
- }
1033
- import(from, subset) {
1034
- for (const key of keys(manage(this), subset))
1035
- if (key in from)
1036
- this[key] = from[key];
1037
- }
1038
- export(subset) {
1039
- const control = manage(this);
1040
- const output = {};
1041
- for (const key of keys(control, subset))
1042
- output[key] = control.state[key];
1043
- return output;
1044
- }
1045
- update(arg, tag) {
1046
- const control = manage(this);
1047
- if (typeof arg == "function")
1048
- arg = select(this, arg);
1049
- if (typeof arg == "boolean") {
1050
- if (!control.pending === arg)
1051
- return Promise.reject(Oops$2.StrictUpdate(arg));
1052
- }
1053
- else if (arg) {
1054
- control.update(arg);
1055
- if (1 in arguments && arg in this) {
1056
- const method = this[arg];
1057
- if (typeof method == "function")
1058
- if (typeof tag != "boolean")
1059
- method.call(this, tag);
1060
- else if (tag)
1061
- method.call(this);
1062
- }
1063
- }
1064
- return {
1065
- then(callback) {
1066
- if (callback)
1067
- if (control.pending)
1068
- control.waiting.add(callback);
1069
- else
1070
- callback(false);
1071
- else
1072
- throw Oops$2.NoChaining();
1073
- }
1074
- };
1075
- }
1076
- destroy() {
1077
- this.update("willDestroy", true);
1078
- }
1079
- toString() {
1080
- return this.constructor.name;
1081
- }
1082
- static create(...args) {
1083
- const instance = new this(...args);
1084
- manage(instance);
1085
- return instance;
1250
+ return useNew(this, callback);
1086
1251
  }
1087
1252
  static new(callback) {
1088
- const instance = useLazy(this, callback);
1089
- instance.update("willRender", true);
1090
- return instance;
1091
- }
1092
- static find(strict) {
1093
- return useFromContext(this, strict);
1253
+ return usePassive(this, callback);
1094
1254
  }
1095
1255
  static get(key) {
1096
- const instance = this.find(!!key);
1097
- return (typeof key == "function" ?
1098
- key(instance) :
1099
- typeof key == "string" ?
1100
- instance[key] :
1101
- instance);
1256
+ const instance = useContext(this, key !== false);
1257
+ return (typeof key == "string" ?
1258
+ instance[key] :
1259
+ instance);
1102
1260
  }
1103
1261
  static tap(key, expect) {
1104
- return this.find(true).tap(key, expect);
1262
+ return this.get().tap(key, expect);
1105
1263
  }
1106
1264
  static tag(id) {
1107
- return this.find(true).tag(id);
1265
+ return this.get().tag(id);
1108
1266
  }
1109
1267
  static use(callback) {
1110
- const instance = useModel(this, callback);
1111
- useComponentLifecycle(instance[LOCAL]);
1112
- usePeerContext(instance.get);
1113
- return instance;
1268
+ return useModel(this, callback);
1114
1269
  }
1115
1270
  static uses(props, only) {
1116
1271
  return this.use(instance => {
@@ -1122,131 +1277,11 @@ class Model {
1122
1277
  instance.import(props, only);
1123
1278
  return instance;
1124
1279
  }
1125
- static meta(path) {
1280
+ static meta(path, expect) {
1126
1281
  return typeof path == "function"
1127
- ? useComputed(this, path)
1128
- : useWatcher(this, path);
1282
+ ? useComputed(this, path, expect)
1283
+ : useActive(this, path, expect);
1129
1284
  }
1130
- static isTypeof(maybe) {
1131
- return (typeof maybe == "function" &&
1132
- maybe.prototype instanceof this);
1133
- }
1134
- }
1135
- Model.CONTROL = CONTROL;
1136
- Model.STATE = STATE;
1137
- Model.LOCAL = LOCAL;
1138
- Model.WHY = UPDATE;
1139
- defineLazy(Model, CONTROL, function () {
1140
- return new Controller(this).start();
1141
- });
1142
- function defer(on, method) {
1143
- const { subject, waiting } = on;
1144
- const real = subject[method];
1145
- subject[method] = (...args) => {
1146
- let done;
1147
- waiting.add(() => {
1148
- done = real.apply(subject, args);
1149
- });
1150
- return () => done();
1151
- };
1152
- }
1153
-
1154
- const Parent = new WeakMap();
1155
- const Oops$1 = issues({
1156
- ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
1157
- UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
1158
- UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
1159
- BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
1160
- IsReadOnly: (owner, key) => `${owner}.${key} is set to read-only, but tried to reassign assign.`,
1161
- MustBeDefined: (owner, key) => `${owner}.${key} must have initial value, as a read-only property.`
1162
- });
1163
- function bootstrap(object) {
1164
- const breakdown = getOwnPropertyDescriptors(object);
1165
- const control = new Model();
1166
- for (const key in breakdown)
1167
- defineProperty(control, key, breakdown[key]);
1168
- return control;
1169
- }
1170
- function use(input, argument) {
1171
- return child(function use(key) {
1172
- const { subject } = this;
1173
- // `true` => readonly
1174
- // `false` => writable, may be undefined
1175
- // `undefined` => writable (default)
1176
- let mode = argument;
1177
- let current;
1178
- const onUpdate = (next, initial) => {
1179
- if (mode === true && !initial)
1180
- throw Oops$1.IsReadOnly(subject, key);
1181
- if (next) {
1182
- current = next instanceof Model
1183
- ? next : bootstrap(next);
1184
- Parent.set(current, subject);
1185
- manage(current);
1186
- }
1187
- else if (mode === undefined)
1188
- throw Oops$1.UndefinedNotAllowed(key);
1189
- else
1190
- current = undefined;
1191
- if (typeof argument == "function")
1192
- return argument(current);
1193
- };
1194
- if (input) {
1195
- current =
1196
- Model.isTypeof(input) ? new input() :
1197
- input instanceof Model ? input :
1198
- typeof input === "function" ? input() :
1199
- typeof input === "object" ? bootstrap(input) :
1200
- Oops$1.BadArgument(typeof input).throw();
1201
- if (current)
1202
- mode = onUpdate(current, true) || mode;
1203
- else if (mode == true)
1204
- throw Oops$1.MustBeDefined(subject, key);
1205
- }
1206
- else
1207
- mode = false;
1208
- this.manage(key, current, onUpdate);
1209
- return () => current;
1210
- });
1211
- }
1212
- function parent(Expects, required) {
1213
- return apply(function parent() {
1214
- const child = this.subject;
1215
- const expected = Expects.name;
1216
- const value = Parent.get(this.subject);
1217
- if (!value) {
1218
- if (required)
1219
- throw Oops$1.ParentRequired(expected, child);
1220
- }
1221
- else if (!(value instanceof Expects))
1222
- throw Oops$1.UnexpectedParent(expected, child, value);
1223
- return { value };
1224
- });
1225
- }
1226
-
1227
- function on(initial, cb) {
1228
- return apply(function on(key) {
1229
- this.manage(key, initial, cb && createValueEffect(cb));
1230
- });
1231
- }
1232
- function memo(factory, defer) {
1233
- return apply(function memo(key) {
1234
- const source = this.subject;
1235
- const get = () => factory.call(source);
1236
- if (defer)
1237
- defineLazy(source, key, get);
1238
- else
1239
- define(source, key, get());
1240
- });
1241
- }
1242
- function lazy(value) {
1243
- return apply(function lazy(key) {
1244
- const source = this.subject;
1245
- source[key] = value;
1246
- defineProperty(this.state, key, {
1247
- get: () => source[key]
1248
- });
1249
- });
1250
1285
  }
1251
1286
 
1252
1287
  const Oops = issues({
@@ -1254,35 +1289,32 @@ const Oops = issues({
1254
1289
  GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
1255
1290
  });
1256
1291
  const Active = new WeakMap();
1257
- class Singleton extends Model {
1258
- static get current() {
1259
- return Active.get(this);
1260
- }
1292
+ class Singleton extends MVC {
1261
1293
  static create(...args) {
1262
1294
  const Type = this;
1263
1295
  if (Active.has(Type))
1264
1296
  throw Oops.GlobalExists(this.name);
1265
- let instance = super.create(...args);
1297
+ const instance = super.create(...args);
1266
1298
  Active.set(Type, instance);
1267
1299
  return instance;
1268
1300
  }
1269
- static update(updates) {
1270
- const instance = this.current || this.create();
1301
+ static set(updates) {
1302
+ const instance = Active.get(this) || this.create();
1271
1303
  instance.import(updates);
1272
1304
  return instance.update();
1273
1305
  }
1274
- static is() {
1275
- return this.find(true);
1276
- }
1277
- static find(strict) {
1278
- const instance = this.current;
1279
- if (!instance && strict)
1306
+ static get(arg) {
1307
+ const instance = Active.get(this);
1308
+ if (!instance && arg !== false)
1280
1309
  throw Oops.GlobalDoesNotExist(this.name);
1281
- return instance;
1310
+ return (typeof arg == "string" ?
1311
+ instance[arg] :
1312
+ instance);
1282
1313
  }
1283
1314
  static reset() {
1284
- if (this.current)
1285
- this.current.destroy();
1315
+ const current = Active.get(this);
1316
+ if (current)
1317
+ current.destroy();
1286
1318
  }
1287
1319
  destroy() {
1288
1320
  super.destroy();
@@ -1291,20 +1323,21 @@ class Singleton extends Model {
1291
1323
  }
1292
1324
 
1293
1325
  exports.Consumer = Consumer;
1294
- exports.Model = Model;
1326
+ exports.Model = MVC;
1295
1327
  exports.Provider = Provider;
1296
1328
  exports.Singleton = Singleton;
1297
1329
  exports.act = act;
1298
1330
  exports.apply = apply;
1299
1331
  exports.child = child;
1300
- exports["default"] = Model;
1332
+ exports["default"] = MVC;
1301
1333
  exports.from = from;
1302
1334
  exports.lazy = lazy;
1303
- exports.memo = memo;
1335
+ exports.memo = set;
1304
1336
  exports.on = on;
1305
1337
  exports.parent = parent;
1306
1338
  exports.pending = pending;
1307
1339
  exports.ref = ref;
1340
+ exports.set = set;
1308
1341
  exports.tap = tap;
1309
- exports.use = use;
1342
+ exports.use = use$1;
1310
1343
  //# sourceMappingURL=index.js.map