@expressive/mvc 0.33.0 → 0.35.0-alpha.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 DELETED
@@ -1,1052 +0,0 @@
1
- /******************************************************************************
2
- Copyright (c) Microsoft Corporation.
3
-
4
- Permission to use, copy, modify, and/or distribute this software for any
5
- purpose with or without fee is hereby granted.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
- PERFORMANCE OF THIS SOFTWARE.
14
- ***************************************************************************** */
15
-
16
- function __awaiter(thisArg, _arguments, P, generator) {
17
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
- return new (P || (P = Promise))(function (resolve, reject) {
19
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
- step((generator = generator.apply(thisArg, _arguments || [])).next());
23
- });
24
- }
25
-
26
- class Issue extends Error {
27
- constructor() {
28
- super(...arguments);
29
- // drop first line (error factory) in stack trace.
30
- this.stack = this.stack.replace(/\n.+/, "");
31
- }
32
- warn() {
33
- console.warn(this.message);
34
- }
35
- }
36
- function issues(register) {
37
- const Library = {};
38
- for (const name in register)
39
- Library[name] = (...args) => new Issue(register[name].apply(null, args));
40
- return Library;
41
- }
42
-
43
- const { assign, create, defineProperties, defineProperty, entries, keys, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
44
-
45
- const Oops$8 = issues({
46
- NotFound: (name) => `Could not find ${name} in context.`
47
- });
48
- function get$1(argument) {
49
- return Control.get((dispatch, context) => {
50
- const refresh = () => dispatch(x => x + 1);
51
- let onUpdate;
52
- let value;
53
- if (typeof argument !== "function") {
54
- const got = context.get(this);
55
- if (got)
56
- value = argument === undefined
57
- ? Control.watch(got, k => k ? onUpdate : undefined)
58
- : got;
59
- else if (argument !== false)
60
- throw Oops$8.NotFound(this);
61
- return {
62
- mount() {
63
- onUpdate = refresh;
64
- return () => onUpdate = null;
65
- },
66
- render: () => value
67
- };
68
- }
69
- let compute = argument;
70
- let suspense;
71
- let getValue;
72
- let factory;
73
- let proxy;
74
- const found = context.get(this);
75
- if (!found)
76
- throw Oops$8.NotFound(this);
77
- function forceUpdate(action) {
78
- if (typeof action == "function")
79
- action = action();
80
- if (getValue)
81
- didUpdate(getValue());
82
- else
83
- refresh();
84
- if (action)
85
- return action.finally(refresh);
86
- }
87
- function didUpdate(got) {
88
- value = got;
89
- if (suspense) {
90
- suspense();
91
- suspense = undefined;
92
- }
93
- else
94
- refresh();
95
- }
96
- proxy = Control.watch(found, () => factory ? null : onUpdate);
97
- getValue = () => compute.call(proxy, proxy, forceUpdate);
98
- value = getValue();
99
- if (value === null) {
100
- getValue = undefined;
101
- onUpdate = null;
102
- return;
103
- }
104
- if (typeof value == "function") {
105
- const get = value;
106
- Control.watch(proxy, () => onUpdate);
107
- factory = true;
108
- compute = () => get();
109
- value = get();
110
- }
111
- if (value instanceof Promise) {
112
- onUpdate = null;
113
- value.then(didUpdate);
114
- value = undefined;
115
- }
116
- else
117
- onUpdate = () => {
118
- const next = getValue();
119
- if (value !== next)
120
- didUpdate(next);
121
- };
122
- return {
123
- mount: () => () => {
124
- onUpdate = null;
125
- },
126
- render: () => {
127
- if (value !== undefined)
128
- return value;
129
- if (onUpdate)
130
- return null;
131
- throw new Promise(res => {
132
- suspense = res;
133
- });
134
- }
135
- };
136
- });
137
- }
138
-
139
- function use$1(apply, repeat) {
140
- const render = Control.use(dispatch => {
141
- const instance = this.new();
142
- const local = Control.watch(instance, () => onUpdate);
143
- const refresh = () => dispatch(x => x + 1);
144
- let onUpdate;
145
- let shouldApply = !!apply;
146
- return {
147
- instance,
148
- mount() {
149
- onUpdate = refresh;
150
- return () => {
151
- onUpdate = null;
152
- instance.null();
153
- };
154
- },
155
- render(props) {
156
- if (shouldApply) {
157
- onUpdate = undefined;
158
- if (typeof props == "function")
159
- props(instance);
160
- else if (props)
161
- for (const key in instance)
162
- if (props.hasOwnProperty(key))
163
- instance[key] = props[key];
164
- if (!repeat)
165
- shouldApply = false;
166
- instance.set(0).then(() => onUpdate = refresh);
167
- }
168
- return local;
169
- }
170
- };
171
- });
172
- return render(apply);
173
- }
174
-
175
- const Oops$7 = issues({
176
- NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
177
- Destoryed: () => "Model is destroyed."
178
- });
179
- function suspense(source, key) {
180
- const error = Oops$7.NotReady(source.subject, key);
181
- const watch = source.observers.get(key);
182
- const promise = new Promise((resolve, reject) => {
183
- function onUpdate(key) {
184
- if (key)
185
- return () => {
186
- if (source.state[key] !== undefined) {
187
- watch.delete(onUpdate);
188
- resolve();
189
- }
190
- };
191
- if (key === null)
192
- reject(Oops$7.Destoryed());
193
- }
194
- watch.add(onUpdate);
195
- });
196
- return assign(promise, {
197
- toString: () => String(error),
198
- name: "Suspense",
199
- message: error.message,
200
- stack: error.stack
201
- });
202
- }
203
- function mayRetry(fn) {
204
- const retry = (err) => {
205
- if (err instanceof Promise)
206
- return err.then(compute);
207
- else
208
- throw err;
209
- };
210
- const compute = () => {
211
- try {
212
- const output = fn();
213
- return output instanceof Promise
214
- ? output.catch(retry)
215
- : output;
216
- }
217
- catch (err) {
218
- return retry(err);
219
- }
220
- };
221
- return compute();
222
- }
223
-
224
- const Oops$6 = issues({
225
- BadCallback: () => `Callback for effect-callback may only return a function.`
226
- });
227
- function createEffect(source, callback) {
228
- return control(source, self => {
229
- let { subject } = self;
230
- let unSet;
231
- let busy = false;
232
- function invoke() {
233
- if (busy)
234
- return;
235
- const output = mayRetry(() => {
236
- if (typeof unSet == "function")
237
- unSet();
238
- unSet = callback.call(subject, subject);
239
- if (unSet instanceof Promise)
240
- unSet = undefined;
241
- if (unSet && typeof unSet !== "function")
242
- throw Oops$6.BadCallback();
243
- });
244
- if (output instanceof Promise) {
245
- output.finally(() => busy = false);
246
- busy = true;
247
- }
248
- }
249
- let refresh;
250
- subject = watch(subject, () => refresh);
251
- self.followers.add(key => (key === null || refresh === null ? refresh : undefined));
252
- invoke();
253
- refresh = invoke;
254
- return () => refresh = null;
255
- });
256
- }
257
- function createValueEffect(callback, ignoreNull) {
258
- let unSet;
259
- return function (value) {
260
- if (typeof unSet == "function")
261
- unSet = void unSet(value);
262
- if (value === null && ignoreNull)
263
- return;
264
- const out = callback.call(this, value);
265
- if (typeof out == "boolean")
266
- return out;
267
- if (!out || out instanceof Promise)
268
- return;
269
- if (typeof out == "function")
270
- unSet = out;
271
- else
272
- throw Oops$6.BadCallback();
273
- };
274
- }
275
-
276
- function getMethod(argument, callback, once) {
277
- if (typeof argument == "function")
278
- return createEffect(this, argument);
279
- const self = control(this, true);
280
- function get(key) {
281
- const value = self.state[key];
282
- return value instanceof Model ? value.get() : value;
283
- }
284
- const extract = typeof argument == "string"
285
- ? () => get(argument)
286
- : () => {
287
- const output = {};
288
- for (const key of argument || keys(self.state))
289
- output[key] = get(key);
290
- return output;
291
- };
292
- if (typeof callback != "function")
293
- return extract();
294
- const select = typeof argument == "string" ? [argument] : argument;
295
- const invoke = () => callback(extract(), self.latest || []);
296
- if (select)
297
- for (const key of select)
298
- try {
299
- const value = self.subject[key];
300
- if (!(key in self.state))
301
- self.watch(key, { value });
302
- }
303
- catch (e) {
304
- // TODO: should this be caught?
305
- }
306
- if (once === undefined)
307
- invoke();
308
- const remove = self.addListener(key => {
309
- if (!select || select.includes(key)) {
310
- if (once)
311
- remove();
312
- return invoke;
313
- }
314
- });
315
- return remove;
316
- }
317
- function setMethod(arg1, arg2) {
318
- const self = control(this, true);
319
- const { state } = self;
320
- let timeout = 0;
321
- switch (typeof arg1) {
322
- case "string":
323
- if (1 in arguments)
324
- if (arg1 in state)
325
- state[arg1] = arg2;
326
- else
327
- self.watch(arg1, { value: arg2 });
328
- self.update(arg1);
329
- break;
330
- case "object":
331
- for (const key in state)
332
- if (key in arg1 && (!arg2 || arg2.includes(key))) {
333
- state[key] = arg1[key];
334
- self.update(key);
335
- }
336
- break;
337
- default:
338
- timeout = arg1;
339
- }
340
- return new Promise((resolve) => {
341
- if (!self.frame.size && timeout === 0)
342
- resolve(false);
343
- const remove = self.addListener(() => {
344
- remove();
345
- return () => resolve(self.latest);
346
- });
347
- if (timeout > 0)
348
- setTimeout(() => {
349
- remove();
350
- resolve(false);
351
- }, timeout);
352
- });
353
- }
354
-
355
- class Model {
356
- constructor(id) {
357
- new Control(this, id === undefined ? uid() : id);
358
- }
359
- /** Mark this instance for garbage collection. */
360
- null() {
361
- control(this, true).clear();
362
- }
363
- /**
364
- * Creates a new instance of this controller.
365
- *
366
- * Beyond `new this(...)`, method will activate managed-state.
367
- *
368
- * @param args - arguments sent to constructor
369
- */
370
- static new(...args) {
371
- const instance = new this(...args);
372
- control(instance, true);
373
- return instance;
374
- }
375
- /**
376
- * Static equivalent of `x instanceof this`.
377
- *
378
- * Will determine if provided class is a subtype of this one.
379
- */
380
- static is(maybe) {
381
- return (typeof maybe == "function" &&
382
- maybe.prototype instanceof this);
383
- }
384
- }
385
- Model.get = get$1;
386
- Model.use = use$1;
387
- defineProperty(Model, "toString", {
388
- value() {
389
- return this.name;
390
- }
391
- });
392
- defineProperties(Model.prototype, {
393
- get: { value: getMethod },
394
- set: { value: setMethod },
395
- toString: {
396
- configurable: true,
397
- value() {
398
- return `${this.constructor.name}-${control(this).id}`;
399
- }
400
- }
401
- });
402
- /* TODO: Remove below on 1.0.0 release. */
403
- defineProperty(Model, "isTypeof", {
404
- get() {
405
- throw new Error("Model.isTypeof method was renamed. Use Model.is instead.");
406
- }
407
- });
408
- defineProperties(Model.prototype, {
409
- is: {
410
- configurable: true,
411
- get() {
412
- throw new Error("Model.is property is now is only available from a hook.");
413
- }
414
- },
415
- on: {
416
- configurable: true,
417
- writable: true,
418
- value() {
419
- throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
420
- }
421
- }
422
- });
423
- /** Random alphanumberic of length 6. Will always start with a letter. */
424
- function uid() {
425
- return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
426
- }
427
-
428
- const Oops$5 = issues({
429
- BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
430
- });
431
- const REGISTER = new WeakMap();
432
- const OBSERVER = new WeakMap();
433
- const INSTRUCT = new Map();
434
- const PENDING$1 = new WeakMap();
435
- const PARENTS = new WeakMap();
436
- class Control {
437
- constructor(subject, id) {
438
- this.state = {};
439
- this.frame = new Set();
440
- this.followers = new Set();
441
- this.observers = new Map([["", this.followers]]);
442
- this.id = id;
443
- this.subject = subject;
444
- REGISTER.set(subject, this);
445
- if (id !== false)
446
- PENDING$1.set(this, new Set(Control.ready));
447
- }
448
- add(key) {
449
- const { value } = getOwnPropertyDescriptor(this.subject, key);
450
- const instruction = INSTRUCT.get(value);
451
- if (typeof instruction == "function") {
452
- INSTRUCT.delete(value);
453
- instruction(this, key);
454
- }
455
- else if (value instanceof Model)
456
- setRecursive(this, key, value);
457
- else
458
- this.watch(key, { value });
459
- }
460
- watch(key, output) {
461
- const { state } = this;
462
- const { set, enumerable = true } = output;
463
- const subs = new Set();
464
- this.observers.set(key, subs);
465
- if ("value" in output)
466
- state[key] = output.value;
467
- defineProperty(this.subject, key, {
468
- enumerable,
469
- set: set === false
470
- ? undefined
471
- : this.ref(key, set),
472
- get() {
473
- const event = OBSERVER.get(this);
474
- if (event)
475
- subs.add(event);
476
- const value = output.get
477
- ? output.get(this) : state[key];
478
- return event && REGISTER.has(value)
479
- ? watch(value, event)
480
- : value;
481
- }
482
- });
483
- }
484
- ref(key, callback) {
485
- const { state, subject } = this;
486
- return (value) => {
487
- if (value !== state[key])
488
- switch (callback && callback.call(subject, value)) {
489
- case undefined:
490
- state[key] = value;
491
- case true:
492
- this.update(key);
493
- }
494
- };
495
- }
496
- update(key) {
497
- const { frame } = this;
498
- if (frame.has(key))
499
- return;
500
- if (!frame.size) {
501
- this.latest = undefined;
502
- requestUpdateFrame(() => {
503
- this.latest = Array.from(frame);
504
- this.followers.forEach(cb => {
505
- const notify = cb(undefined, this);
506
- if (notify)
507
- requestUpdateFrame(notify);
508
- });
509
- frame.clear();
510
- });
511
- }
512
- frame.add(key);
513
- for (const k of ["", key]) {
514
- const subs = this.observers.get(k);
515
- subs && subs.forEach(cb => {
516
- const notify = cb(key, this);
517
- if (notify === null)
518
- subs.delete(cb);
519
- else if (notify)
520
- requestUpdateFrame(notify);
521
- });
522
- }
523
- }
524
- addListener(fn) {
525
- this.followers.add(fn);
526
- return () => this.followers.delete(fn);
527
- }
528
- clear() {
529
- this.observers.forEach(subs => {
530
- subs.forEach(fn => {
531
- const cb = fn(null, this);
532
- cb && cb();
533
- });
534
- });
535
- this.observers.clear();
536
- }
537
- }
538
- Control.ready = new Set();
539
- Control.after = new Set();
540
- Control.before = new Set();
541
- Control.pending = new Set();
542
- Control.for = control;
543
- Control.apply = apply;
544
- Control.watch = watch;
545
- function control(subject, ready) {
546
- const control = REGISTER.get(subject);
547
- const pending = PENDING$1.get(control);
548
- if (typeof ready == "function") {
549
- if (!pending)
550
- return ready(control);
551
- let done;
552
- pending.add(() => done = ready(control));
553
- return () => done && done();
554
- }
555
- if (pending && ready) {
556
- for (const key in control.subject)
557
- control.add(key);
558
- PENDING$1.delete(control);
559
- pending.forEach(cb => cb(control));
560
- }
561
- return control;
562
- }
563
- function requestUpdateFrame(event) {
564
- const { after, before, pending } = Control;
565
- if (!pending.size)
566
- setTimeout(() => {
567
- before.forEach(x => x());
568
- pending.forEach(notify => {
569
- try {
570
- notify();
571
- }
572
- catch (err) {
573
- console.error(err);
574
- }
575
- });
576
- pending.clear();
577
- after.forEach(x => x());
578
- }, 0);
579
- pending.add(event);
580
- }
581
- function setRecursive(on, key, value) {
582
- const set = (next) => {
583
- if (next instanceof value.constructor) {
584
- on.state[key] = next;
585
- parent(next, on.subject);
586
- control(next, true);
587
- return true;
588
- }
589
- throw Oops$5.BadAssignment(`${on.subject}.${key}`, value.constructor, next);
590
- };
591
- on.watch(key, { set });
592
- set(value);
593
- }
594
- function parent(child, assign) {
595
- if (!assign)
596
- return PARENTS.get(child);
597
- PARENTS.set(child, assign);
598
- }
599
- function watch(value, cb) {
600
- if (!OBSERVER.has(value)) {
601
- const control = REGISTER.get(value);
602
- value = defineProperty(create(value), "is", { value });
603
- REGISTER.set(value, control);
604
- }
605
- OBSERVER.set(value, cb);
606
- return value;
607
- }
608
- function apply(instruction) {
609
- const placeholder = Symbol("instruction");
610
- INSTRUCT.set(placeholder, (onto, key) => {
611
- delete onto.subject[key];
612
- const output = instruction.call(onto, key, onto);
613
- if (output)
614
- onto.watch(key, typeof output == "function" ? { get: output } : output);
615
- });
616
- return placeholder;
617
- }
618
-
619
- const Oops$4 = issues({
620
- DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
621
- });
622
- function run(task) {
623
- return apply((key, control) => {
624
- let pending = false;
625
- const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
626
- if (pending)
627
- return Promise.reject(Oops$4.DuplicatePending(key));
628
- pending = true;
629
- control.update(key);
630
- try {
631
- return yield mayRetry(() => (task.apply(control.subject, args)));
632
- }
633
- finally {
634
- pending = false;
635
- control.update(key);
636
- }
637
- });
638
- control.state[key] = undefined;
639
- defineProperty(invoke, "active", {
640
- get: () => pending
641
- });
642
- return {
643
- value: invoke,
644
- set: false
645
- };
646
- });
647
- }
648
-
649
- const Oops$3 = issues({
650
- PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
651
- Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
652
- Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}.`,
653
- Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
654
- AmbientRequired: (requested, requester) => `Attempted to find an instance of ${requested} in context. It is required by ${requester}, but one could not be found.`
655
- });
656
- function get(arg0, arg1) {
657
- return apply((key, control) => {
658
- let { subject } = control;
659
- if (typeof arg0 == "symbol")
660
- throw Oops$3.PeerNotAllowed(subject, key);
661
- let source = cb => cb(subject);
662
- if (arg0 instanceof Model)
663
- subject = arg0;
664
- else if (Model.is(arg0)) {
665
- const hasParent = parent(subject);
666
- if (!hasParent) {
667
- if (arg1 === true)
668
- throw Oops$3.Required(arg0, subject);
669
- const fetch = Control.has(subject);
670
- source = got => {
671
- fetch(context => {
672
- const model = context.get(arg0);
673
- if (model)
674
- got(model);
675
- else if (arg1 !== false)
676
- throw Oops$3.AmbientRequired(arg0, subject);
677
- });
678
- };
679
- }
680
- else if (!arg0 || hasParent instanceof arg0)
681
- subject = hasParent;
682
- else
683
- throw Oops$3.Unexpected(arg0, subject, hasParent);
684
- }
685
- else if (typeof arg0 == "function")
686
- arg1 = arg0.call(subject, key, subject);
687
- return typeof arg1 == "function"
688
- ? computed(control, key, source, arg1)
689
- : recursive(control, key, source, arg1);
690
- });
691
- }
692
- function recursive(parent, key, source, required) {
693
- let waiting;
694
- if (source)
695
- source((got) => {
696
- parent.state[key] = got;
697
- if (waiting)
698
- parent.update(key);
699
- });
700
- waiting = true;
701
- return () => {
702
- const value = parent.state[key];
703
- if (value)
704
- return value;
705
- if (required !== false)
706
- throw suspense(parent, key);
707
- };
708
- }
709
- const ORDER = new WeakMap();
710
- const PENDING = new Set();
711
- let OFFSET = 0;
712
- function computed(parent, key, source, setter) {
713
- const { state } = parent;
714
- let proxy;
715
- let active;
716
- let isAsync;
717
- let reset;
718
- function compute(initial) {
719
- if (parent.frame.has(key))
720
- return;
721
- let next;
722
- try {
723
- next = setter.call(proxy, proxy);
724
- }
725
- catch (err) {
726
- Oops$3.Failed(parent.subject, key, initial).warn();
727
- if (initial)
728
- throw err;
729
- console.error(err);
730
- }
731
- if (next !== state[key]) {
732
- state[key] = next;
733
- if (!initial || isAsync)
734
- parent.update(key);
735
- }
736
- }
737
- function connect(model) {
738
- if (reset)
739
- reset();
740
- let done;
741
- reset = () => done = true;
742
- proxy = watch(model, (_, control) => {
743
- if (done)
744
- return null;
745
- if (control !== parent)
746
- compute();
747
- else
748
- PENDING.add(compute);
749
- });
750
- try {
751
- compute(true);
752
- }
753
- finally {
754
- ORDER.set(compute, OFFSET++);
755
- }
756
- }
757
- return () => {
758
- if (!active) {
759
- active = true;
760
- source(connect);
761
- isAsync = true;
762
- }
763
- if (!proxy)
764
- throw suspense(parent, key);
765
- if (PENDING.delete(compute))
766
- compute();
767
- return state[key];
768
- };
769
- }
770
- function flushComputed() {
771
- while (PENDING.size) {
772
- let compute;
773
- for (const item of PENDING)
774
- if (!compute || ORDER.get(item) < ORDER.get(compute))
775
- compute = item;
776
- PENDING.delete(compute);
777
- compute();
778
- }
779
- }
780
- Control.before.add(flushComputed);
781
-
782
- const Oops$2 = issues({
783
- BadRefObject: () => `ref instruction does not support object which is not 'this'`
784
- });
785
- function ref(arg, arg2) {
786
- return apply((key, source) => {
787
- let value = {};
788
- if (typeof arg != "object")
789
- value = createRef(source, key, arg && createValueEffect(arg, arg2 !== false));
790
- else if (arg !== source.subject)
791
- throw Oops$2.BadRefObject();
792
- else
793
- for (const key in source.state)
794
- defineProperty(value, key, typeof arg2 == "function" ? {
795
- configurable: true,
796
- get() {
797
- const out = arg2(key);
798
- defineProperty(value, key, { value: out });
799
- return out;
800
- }
801
- } : {
802
- value: createRef(source, key)
803
- });
804
- source.state[key] = undefined;
805
- source.observers.set(key, new Set());
806
- defineProperty(source.subject, key, { value });
807
- });
808
- }
809
- function createRef(src, key, cb) {
810
- const refObjectFunction = src.ref(key, cb);
811
- defineProperty(refObjectFunction, "current", {
812
- set: refObjectFunction,
813
- get: () => src.state[key]
814
- });
815
- return refObjectFunction;
816
- }
817
-
818
- const Oops$1 = issues({
819
- ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
820
- NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
821
- });
822
- function set(value, argument) {
823
- return apply((key, control) => {
824
- const { state, subject } = control;
825
- if (typeof value == "function" || value instanceof Promise) {
826
- const output = {};
827
- const init = () => {
828
- try {
829
- if (typeof value == "function")
830
- value = mayRetry(value.bind(subject, key, subject));
831
- if (value instanceof Promise) {
832
- const pending = value
833
- .then(value => {
834
- output.get = undefined;
835
- state[key] = value;
836
- return value;
837
- })
838
- .catch(err => {
839
- output.get = () => { throw err; };
840
- })
841
- .finally(() => {
842
- control.update(key);
843
- });
844
- if (argument !== false)
845
- return () => {
846
- const { message, stack } = Oops$1.NotReady(subject, key);
847
- throw assign(pending, { message, stack });
848
- };
849
- }
850
- else
851
- state[key] = value;
852
- }
853
- catch (err) {
854
- Oops$1.ComputeFailed(subject, key).warn();
855
- throw err;
856
- }
857
- };
858
- if (argument)
859
- init();
860
- else
861
- output.get = () => {
862
- const get = output.get =
863
- key in state ? undefined : init();
864
- return get ? get() : state[key];
865
- };
866
- return output;
867
- }
868
- const set = typeof argument == "function"
869
- ? createValueEffect(argument)
870
- : undefined;
871
- if (value !== undefined) {
872
- state[key] = value;
873
- return { set };
874
- }
875
- const output = {
876
- get() {
877
- if (key in state)
878
- return state[key];
879
- throw suspense(control, key);
880
- }
881
- };
882
- if (set)
883
- output.set = function (value) {
884
- output.set = set;
885
- state[key] = state[key];
886
- return set.call(this, value);
887
- };
888
- return output;
889
- });
890
- }
891
-
892
- function use(input, argument) {
893
- return apply((key, source) => {
894
- const { state, subject } = source;
895
- if (typeof input === "function")
896
- input = new input();
897
- function set(next) {
898
- if (next instanceof Model) {
899
- parent(next, subject);
900
- control(next, true);
901
- }
902
- else if (next)
903
- next = manage(next);
904
- state[key] = next;
905
- if (typeof argument == "function")
906
- argument(next);
907
- return true;
908
- }
909
- set(input);
910
- return { set };
911
- });
912
- }
913
- function manage(next) {
914
- const subject = assign(create(next), {
915
- get: getMethod,
916
- set: setMethod
917
- });
918
- const control = new Control(subject, false);
919
- for (const key in control.state = next)
920
- control.watch(key, {});
921
- return subject;
922
- }
923
-
924
- const Oops = issues({
925
- MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
926
- });
927
- class Context {
928
- constructor() {
929
- this.table = new WeakMap();
930
- this.layer = new Map();
931
- }
932
- has(T) {
933
- let key = this.table.get(T);
934
- if (!key) {
935
- key = Symbol(T.name);
936
- this.table.set(T, key);
937
- }
938
- return key;
939
- }
940
- get(Type) {
941
- const result = this[this.has(Type)];
942
- if (result === null)
943
- throw Oops.MultipleExist(Type);
944
- return result;
945
- }
946
- include(inputs) {
947
- const init = new Map();
948
- for (const key in inputs) {
949
- const input = inputs[key];
950
- const exists = this.layer.get(key);
951
- if (!exists) {
952
- const instance = this.add(input);
953
- this.layer.set(key, input);
954
- init.set(instance, true);
955
- }
956
- // Context must force-reset becasue inputs are no longer safe.
957
- else if (exists !== input) {
958
- this.pop();
959
- this.key = uid();
960
- return this.include(inputs);
961
- }
962
- }
963
- for (const [model] of init) {
964
- const { state } = control(model, true);
965
- Object.values(state).forEach(value => {
966
- if (parent(value) === model) {
967
- this.add(value, true);
968
- init.set(value, false);
969
- }
970
- });
971
- }
972
- return init;
973
- }
974
- add(input, implicit) {
975
- let writable = true;
976
- let T;
977
- let I;
978
- if (typeof input == "function") {
979
- T = input;
980
- I = new input();
981
- }
982
- else {
983
- I = control(input).subject;
984
- T = I.constructor;
985
- writable = false;
986
- }
987
- do {
988
- const key = this.has(T);
989
- const value = this.hasOwnProperty(key) ? null : I;
990
- if (value || I !== this[key] && !implicit)
991
- defineProperty(this, key, {
992
- configurable: true,
993
- value,
994
- writable
995
- });
996
- T = getPrototypeOf(T);
997
- } while (T !== Model);
998
- return I;
999
- }
1000
- push() {
1001
- const next = create(this);
1002
- next.layer = new Map();
1003
- return next;
1004
- }
1005
- pop() {
1006
- const items = new Set();
1007
- for (const key of getOwnPropertySymbols(this)) {
1008
- const entry = getOwnPropertyDescriptor(this, key);
1009
- if (entry.writable && entry.value)
1010
- items.add(entry.value);
1011
- delete this[key];
1012
- }
1013
- for (const model of items)
1014
- model.null();
1015
- this.layer.clear();
1016
- }
1017
- }
1018
-
1019
- const STATE = "__state";
1020
- const UPDATE = "__update";
1021
- const CONTROL = "__control";
1022
- const PARENT = "__parent";
1023
- defineProperties(Model.prototype, {
1024
- [CONTROL]: {
1025
- get() {
1026
- return control(this);
1027
- }
1028
- },
1029
- [STATE]: {
1030
- get() {
1031
- return Object.assign({}, control(this).state);
1032
- }
1033
- },
1034
- [UPDATE]: {
1035
- get() {
1036
- return control(this).latest;
1037
- }
1038
- },
1039
- [PARENT]: {
1040
- get() {
1041
- return parent(this);
1042
- }
1043
- }
1044
- });
1045
- const Debug = {
1046
- CONTROL,
1047
- STATE,
1048
- UPDATE,
1049
- PARENT
1050
- };
1051
-
1052
- export { Context, Control, Debug, Model, Model as default, get, ref, run, set, use };