@expressive/mvc 0.17.1 → 0.18.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.d.ts +128 -209
- package/lib/index.esm.js +308 -652
- package/lib/index.js +312 -661
- package/package.json +2 -14
- package/README.md +0 -1666
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
2
2
|
|
|
3
3
|
class Issue extends Error {
|
|
4
4
|
constructor() {
|
|
@@ -17,31 +17,17 @@ function issues(register) {
|
|
|
17
17
|
return Library;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
21
|
-
const UID_CACHE = new WeakMap();
|
|
22
|
-
function assignWeak(into, from) {
|
|
23
|
-
for (const K in from)
|
|
24
|
-
if (K in into)
|
|
25
|
-
into[K] = from[K];
|
|
26
|
-
}
|
|
27
|
-
function uid(object) {
|
|
28
|
-
let uid = UID_CACHE.get(object);
|
|
29
|
-
if (!uid)
|
|
30
|
-
UID_CACHE.set(object, uid = Math.random());
|
|
31
|
-
return uid;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
20
|
const REGISTER$1 = new WeakMap();
|
|
35
21
|
class Subscriber {
|
|
36
|
-
constructor(parent, onUpdate
|
|
37
|
-
this.parent = parent;
|
|
22
|
+
constructor(parent, onUpdate) {
|
|
38
23
|
this.onUpdate = onUpdate;
|
|
39
|
-
this.strict = strict;
|
|
40
24
|
this.active = false;
|
|
41
25
|
this.dependant = new Set();
|
|
42
26
|
this.watch = new Map();
|
|
43
|
-
|
|
27
|
+
if (!(parent instanceof Control))
|
|
28
|
+
parent = Control.for(parent);
|
|
44
29
|
const reset = () => this.latest = undefined;
|
|
30
|
+
const proxy = create(parent.subject);
|
|
45
31
|
REGISTER$1.set(proxy, this);
|
|
46
32
|
defineProperty(this, "proxy", {
|
|
47
33
|
configurable: true,
|
|
@@ -50,6 +36,7 @@ class Subscriber {
|
|
|
50
36
|
return proxy;
|
|
51
37
|
}
|
|
52
38
|
});
|
|
39
|
+
this.parent = parent;
|
|
53
40
|
this.clear = parent.addListener(key => {
|
|
54
41
|
if (this.active)
|
|
55
42
|
this.notify(key);
|
|
@@ -58,15 +45,11 @@ class Subscriber {
|
|
|
58
45
|
get using() {
|
|
59
46
|
return Array.from(this.watch.keys());
|
|
60
47
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
for (const key of keys)
|
|
67
|
-
if (key in values)
|
|
68
|
-
subject[key] = values[key];
|
|
69
|
-
waiting.add(() => this.active = true);
|
|
48
|
+
get(key, using) {
|
|
49
|
+
this.follow(key);
|
|
50
|
+
return using
|
|
51
|
+
? using(this)
|
|
52
|
+
: this.parent.state.get(key);
|
|
70
53
|
}
|
|
71
54
|
follow(key, value) {
|
|
72
55
|
if (value !== undefined)
|
|
@@ -102,11 +85,11 @@ function subscriber(from) {
|
|
|
102
85
|
return REGISTER$1.get(from);
|
|
103
86
|
}
|
|
104
87
|
|
|
105
|
-
const Oops$
|
|
88
|
+
const Oops$8 = issues({
|
|
106
89
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
107
90
|
});
|
|
108
91
|
function suspend(source, key) {
|
|
109
|
-
const error = Oops$
|
|
92
|
+
const error = Oops$8.NotReady(source.subject, key);
|
|
110
93
|
const promise = new Promise(resolve => {
|
|
111
94
|
const release = source.addListener(forKey => {
|
|
112
95
|
if (forKey == key)
|
|
@@ -146,87 +129,7 @@ function mayRetry(fn) {
|
|
|
146
129
|
return compute();
|
|
147
130
|
}
|
|
148
131
|
|
|
149
|
-
const
|
|
150
|
-
const Oops$b = issues({
|
|
151
|
-
BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
|
|
152
|
-
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
153
|
-
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
154
|
-
});
|
|
155
|
-
function getParentForGetInstruction(type, relativeTo, required) {
|
|
156
|
-
const item = getParent(type, relativeTo);
|
|
157
|
-
return (_refresh) => {
|
|
158
|
-
if (item)
|
|
159
|
-
return item;
|
|
160
|
-
if (required)
|
|
161
|
-
throw Oops$b.Required(type.name, relativeTo);
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function getParent(type, from) {
|
|
165
|
-
const value = Parent.get(from);
|
|
166
|
-
if (value && !(value instanceof type))
|
|
167
|
-
throw Oops$b.Unexpected(type.name, from, value);
|
|
168
|
-
return value;
|
|
169
|
-
}
|
|
170
|
-
function getRecursive(key, from) {
|
|
171
|
-
const context = new WeakMap();
|
|
172
|
-
const { state } = from;
|
|
173
|
-
return (local) => {
|
|
174
|
-
if (!state.has(key))
|
|
175
|
-
throw suspend(from, key);
|
|
176
|
-
if (!local)
|
|
177
|
-
return state.get(key);
|
|
178
|
-
if (!context.has(local)) {
|
|
179
|
-
let reset;
|
|
180
|
-
const init = () => {
|
|
181
|
-
if (reset)
|
|
182
|
-
reset();
|
|
183
|
-
const value = state.get(key);
|
|
184
|
-
if (value && controller(value)) {
|
|
185
|
-
const child = new Subscriber(control(value), local.onUpdate);
|
|
186
|
-
if (local.active)
|
|
187
|
-
child.commit();
|
|
188
|
-
local.dependant.add(child);
|
|
189
|
-
context.set(local, child.proxy);
|
|
190
|
-
reset = () => {
|
|
191
|
-
child.release();
|
|
192
|
-
local.dependant.delete(child);
|
|
193
|
-
context.set(local, undefined);
|
|
194
|
-
reset = undefined;
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
local.follow(key, init);
|
|
199
|
-
init();
|
|
200
|
-
}
|
|
201
|
-
return context.get(local);
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function setRecursive(controller, key, initial) {
|
|
205
|
-
const { state, subject } = controller;
|
|
206
|
-
const Type = initial.constructor;
|
|
207
|
-
let get;
|
|
208
|
-
const onUpdate = (next) => {
|
|
209
|
-
state.set(key, next);
|
|
210
|
-
if (!(next instanceof Type))
|
|
211
|
-
throw Oops$b.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
212
|
-
get = getRecursive(key, controller);
|
|
213
|
-
Parent.set(next, subject);
|
|
214
|
-
control(next);
|
|
215
|
-
return true;
|
|
216
|
-
};
|
|
217
|
-
onUpdate(initial);
|
|
218
|
-
defineProperty(subject, key, {
|
|
219
|
-
set: controller.ref(key, onUpdate),
|
|
220
|
-
get() {
|
|
221
|
-
const local = subscriber(this);
|
|
222
|
-
if (local)
|
|
223
|
-
local.follow(key);
|
|
224
|
-
return get(local);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const Oops$a = issues({
|
|
132
|
+
const Oops$7 = issues({
|
|
230
133
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
231
134
|
});
|
|
232
135
|
function createEffect(model, callback, keys) {
|
|
@@ -240,7 +143,7 @@ function createEffect(model, callback, keys) {
|
|
|
240
143
|
if (unSet instanceof Promise)
|
|
241
144
|
unSet = undefined;
|
|
242
145
|
if (unSet && typeof unSet !== "function")
|
|
243
|
-
throw Oops$
|
|
146
|
+
throw Oops$7.BadCallback();
|
|
244
147
|
}
|
|
245
148
|
function invoke() {
|
|
246
149
|
if (busy)
|
|
@@ -284,11 +187,11 @@ function createValueEffect(callback) {
|
|
|
284
187
|
if (typeof out == "function")
|
|
285
188
|
unSet = out;
|
|
286
189
|
else
|
|
287
|
-
throw Oops$
|
|
190
|
+
throw Oops$7.BadCallback();
|
|
288
191
|
};
|
|
289
192
|
}
|
|
290
193
|
|
|
291
|
-
const Oops$
|
|
194
|
+
const Oops$6 = issues({
|
|
292
195
|
Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
|
|
293
196
|
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
294
197
|
StrictUpdate: () => `Expected update but none in progress.`,
|
|
@@ -324,13 +227,13 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
324
227
|
const timeout = (message) => {
|
|
325
228
|
const k = keys ? keys.join(", ") : "any";
|
|
326
229
|
removeListener();
|
|
327
|
-
reject(Oops$
|
|
230
|
+
reject(Oops$6.Timeout(k, message));
|
|
328
231
|
};
|
|
329
232
|
const removeListener = control(source, controller => {
|
|
330
233
|
const pending = controller.frame;
|
|
331
234
|
if (keys === null) {
|
|
332
235
|
if (pending.size)
|
|
333
|
-
reject(Oops$
|
|
236
|
+
reject(Oops$6.StrictNoUpdate());
|
|
334
237
|
else
|
|
335
238
|
resolve(null);
|
|
336
239
|
return;
|
|
@@ -338,7 +241,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
338
241
|
if (keys) {
|
|
339
242
|
if (keys.length) {
|
|
340
243
|
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
341
|
-
reject(Oops$
|
|
244
|
+
reject(Oops$6.KeysExpected(keys[0]));
|
|
342
245
|
return;
|
|
343
246
|
}
|
|
344
247
|
else
|
|
@@ -350,7 +253,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
350
253
|
}
|
|
351
254
|
}
|
|
352
255
|
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
353
|
-
reject(Oops$
|
|
256
|
+
reject(Oops$6.StrictUpdate());
|
|
354
257
|
return;
|
|
355
258
|
}
|
|
356
259
|
else
|
|
@@ -373,8 +276,9 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
373
276
|
});
|
|
374
277
|
}
|
|
375
278
|
|
|
376
|
-
const Oops$
|
|
377
|
-
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining
|
|
279
|
+
const Oops$5 = issues({
|
|
280
|
+
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`,
|
|
281
|
+
NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
|
|
378
282
|
});
|
|
379
283
|
class Model {
|
|
380
284
|
constructor() {
|
|
@@ -391,14 +295,14 @@ class Model {
|
|
|
391
295
|
}
|
|
392
296
|
get(arg1, arg2) {
|
|
393
297
|
const { state } = control(this);
|
|
394
|
-
const extract =
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
298
|
+
const extract = () => {
|
|
299
|
+
if (typeof arg1 == "string")
|
|
300
|
+
return state.get(arg1);
|
|
301
|
+
const output = {};
|
|
302
|
+
for (const key of arg1 || state.keys())
|
|
303
|
+
output[key] = state.get(key);
|
|
304
|
+
return output;
|
|
305
|
+
};
|
|
402
306
|
if (!arg1 || arg2 === undefined)
|
|
403
307
|
return extract();
|
|
404
308
|
if (typeof arg2 == "function")
|
|
@@ -431,15 +335,13 @@ class Model {
|
|
|
431
335
|
return {
|
|
432
336
|
then: (callback) => {
|
|
433
337
|
if (!callback)
|
|
434
|
-
throw Oops$
|
|
338
|
+
throw Oops$5.NoChaining();
|
|
435
339
|
controller.waiting.add(callback);
|
|
436
340
|
}
|
|
437
341
|
};
|
|
438
342
|
}
|
|
439
|
-
/**
|
|
440
|
-
|
|
441
|
-
*/
|
|
442
|
-
end() {
|
|
343
|
+
/** Mark this instance for garbage collection. */
|
|
344
|
+
gc() {
|
|
443
345
|
control(this).clear();
|
|
444
346
|
}
|
|
445
347
|
/**
|
|
@@ -454,6 +356,18 @@ class Model {
|
|
|
454
356
|
control(instance);
|
|
455
357
|
return instance;
|
|
456
358
|
}
|
|
359
|
+
static use() {
|
|
360
|
+
throw Oops$5.NoAdapter("use");
|
|
361
|
+
}
|
|
362
|
+
static get() {
|
|
363
|
+
throw Oops$5.NoAdapter("get");
|
|
364
|
+
}
|
|
365
|
+
static tap() {
|
|
366
|
+
throw Oops$5.NoAdapter("tap");
|
|
367
|
+
}
|
|
368
|
+
static meta() {
|
|
369
|
+
throw Oops$5.NoAdapter("meta");
|
|
370
|
+
}
|
|
457
371
|
/**
|
|
458
372
|
* Static equivalent of `x instanceof this`.
|
|
459
373
|
*
|
|
@@ -468,114 +382,172 @@ defineProperty(Model.prototype, "toString", {
|
|
|
468
382
|
value() {
|
|
469
383
|
return this.constructor.name;
|
|
470
384
|
}
|
|
471
|
-
});
|
|
472
|
-
const FindInstruction = new WeakMap([
|
|
473
|
-
[Model, getParentForGetInstruction]
|
|
474
|
-
]);
|
|
385
|
+
});
|
|
475
386
|
|
|
476
|
-
|
|
387
|
+
/**
|
|
388
|
+
* Run instruction as controller sets itself up.
|
|
389
|
+
* This will specialize the behavior of a given property.
|
|
390
|
+
*/
|
|
391
|
+
function add(instruction, label) {
|
|
392
|
+
const name = label || instruction.name || "pending";
|
|
393
|
+
const placeholder = Symbol(`${name} instruction`);
|
|
394
|
+
PENDING.set(placeholder, (control, key) => {
|
|
395
|
+
let output = instruction.call(control, key, control);
|
|
396
|
+
if (!output)
|
|
397
|
+
return undefined;
|
|
398
|
+
if (typeof output == "function")
|
|
399
|
+
output = { get: output };
|
|
400
|
+
if ("value" in output)
|
|
401
|
+
control.state.set(key, output.value);
|
|
402
|
+
let { enumerable, get, set } = output;
|
|
403
|
+
defineProperty(control.subject, key, {
|
|
404
|
+
enumerable,
|
|
405
|
+
set: (set === false
|
|
406
|
+
? undefined
|
|
407
|
+
: control.ref(key, set)),
|
|
408
|
+
get() {
|
|
409
|
+
const local = subscriber(this);
|
|
410
|
+
return (local ? local.get(key, get) :
|
|
411
|
+
get ? get(local) :
|
|
412
|
+
control.state.get(key));
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
return placeholder;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const Oops$4 = issues({
|
|
477
420
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
|
|
478
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}]
|
|
421
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
|
|
422
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
479
423
|
});
|
|
480
424
|
function get(arg0, arg1) {
|
|
425
|
+
const fetch = this || getParentForGetInstruction;
|
|
481
426
|
return add(function get(key) {
|
|
482
|
-
|
|
483
|
-
// Easy mistake, using a peer, will always be unresolved.
|
|
427
|
+
let { subject } = this;
|
|
484
428
|
if (typeof arg0 == "symbol")
|
|
485
|
-
throw Oops$
|
|
486
|
-
let source;
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
else if (Model.isTypeof(arg0)) {
|
|
494
|
-
source = find(arg0, subject, sourceRequired);
|
|
495
|
-
}
|
|
496
|
-
else if (typeof arg0 == "function") {
|
|
429
|
+
throw Oops$4.PeerNotAllowed(subject, key);
|
|
430
|
+
let source = cb => cb(subject);
|
|
431
|
+
if (arg0 instanceof Model)
|
|
432
|
+
subject = arg0;
|
|
433
|
+
else if (Model.isTypeof(arg0))
|
|
434
|
+
source = fetch(arg0, subject, arg1 !== false);
|
|
435
|
+
else if (typeof arg0 == "function")
|
|
497
436
|
arg1 = arg0.call(subject, key, subject);
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
return getComputed(key, this, source, arg1);
|
|
502
|
-
else {
|
|
503
|
-
const init = source((got) => {
|
|
504
|
-
state.set(key, got);
|
|
505
|
-
this.update(key);
|
|
506
|
-
});
|
|
507
|
-
// TODO: remove fixes suspense test
|
|
508
|
-
if (init || arg1 === false)
|
|
509
|
-
state.set(key, init);
|
|
510
|
-
return getRecursive(key, this);
|
|
511
|
-
}
|
|
437
|
+
return typeof arg1 == "function"
|
|
438
|
+
? getComputed(key, this, source, arg1)
|
|
439
|
+
: getRecursive$1(key, this, source, arg1);
|
|
512
440
|
});
|
|
513
441
|
}
|
|
442
|
+
function getParentForGetInstruction(type, relativeTo, required) {
|
|
443
|
+
const item = getParent(relativeTo, type);
|
|
444
|
+
return callback => {
|
|
445
|
+
if (item)
|
|
446
|
+
callback(item);
|
|
447
|
+
else if (required)
|
|
448
|
+
throw Oops$4.Required(type.name, relativeTo);
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function getRecursive$1(key, parent, source, required) {
|
|
452
|
+
const context = new WeakMap();
|
|
453
|
+
const { state } = parent;
|
|
454
|
+
let waiting;
|
|
455
|
+
source((got) => {
|
|
456
|
+
state.set(key, got);
|
|
457
|
+
if (waiting)
|
|
458
|
+
parent.update(key);
|
|
459
|
+
});
|
|
460
|
+
waiting = true;
|
|
461
|
+
function create(local) {
|
|
462
|
+
let reset;
|
|
463
|
+
local.follow(key, init);
|
|
464
|
+
init();
|
|
465
|
+
function init() {
|
|
466
|
+
if (reset)
|
|
467
|
+
reset();
|
|
468
|
+
const value = state.get(key);
|
|
469
|
+
if (value && controller(value)) {
|
|
470
|
+
const child = new Subscriber(value, local.onUpdate);
|
|
471
|
+
if (local.active)
|
|
472
|
+
child.commit();
|
|
473
|
+
local.dependant.add(child);
|
|
474
|
+
context.set(local, child.proxy);
|
|
475
|
+
reset = () => {
|
|
476
|
+
child.release();
|
|
477
|
+
local.dependant.delete(child);
|
|
478
|
+
context.set(local, undefined);
|
|
479
|
+
reset = undefined;
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return (local) => {
|
|
485
|
+
const value = state.get(key);
|
|
486
|
+
if (!value && required !== false)
|
|
487
|
+
parent.waitFor(key);
|
|
488
|
+
if (!local)
|
|
489
|
+
return value;
|
|
490
|
+
if (!context.has(local))
|
|
491
|
+
create(local);
|
|
492
|
+
return context.get(local);
|
|
493
|
+
};
|
|
494
|
+
}
|
|
514
495
|
function getComputed(key, parent, source, setter) {
|
|
515
496
|
const { state } = parent;
|
|
516
|
-
let
|
|
497
|
+
let local;
|
|
498
|
+
let active;
|
|
499
|
+
let isAsync;
|
|
517
500
|
let order = ORDER.get(parent);
|
|
518
501
|
let pending = KEYS.get(parent);
|
|
519
|
-
let instance;
|
|
520
502
|
if (!order)
|
|
521
503
|
ORDER.set(parent, order = new Map());
|
|
522
504
|
if (!pending)
|
|
523
505
|
KEYS.set(parent, pending = new Set());
|
|
524
|
-
|
|
506
|
+
INFO.set(compute, key);
|
|
507
|
+
function compute(initial) {
|
|
508
|
+
let next;
|
|
525
509
|
try {
|
|
526
|
-
|
|
510
|
+
next = setter.call(local.proxy, local.proxy);
|
|
527
511
|
}
|
|
528
512
|
catch (err) {
|
|
529
|
-
Oops$
|
|
530
|
-
|
|
513
|
+
Oops$4.Failed(parent.subject, key, initial).warn();
|
|
514
|
+
if (initial)
|
|
515
|
+
throw err;
|
|
516
|
+
console.error(err);
|
|
531
517
|
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
518
|
+
if (next !== state.get(key)) {
|
|
519
|
+
state.set(key, next);
|
|
520
|
+
if (!initial || isAsync)
|
|
521
|
+
parent.update(key);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function connect(model) {
|
|
525
|
+
local = new Subscriber(model, (_, control) => {
|
|
540
526
|
if (control !== parent)
|
|
541
|
-
|
|
527
|
+
compute();
|
|
542
528
|
else
|
|
543
|
-
pending.add(
|
|
529
|
+
pending.add(compute);
|
|
544
530
|
});
|
|
545
|
-
|
|
546
|
-
try {
|
|
547
|
-
const value = compute(true);
|
|
548
|
-
state.set(key, value);
|
|
549
|
-
return value;
|
|
550
|
-
}
|
|
551
|
-
finally {
|
|
552
|
-
sub.commit();
|
|
553
|
-
order.set(refresh, order.size);
|
|
554
|
-
}
|
|
555
|
-
};
|
|
556
|
-
const refresh = () => {
|
|
557
|
-
let value;
|
|
531
|
+
local.watch.set(key, false);
|
|
558
532
|
try {
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
catch (e) {
|
|
562
|
-
console.error(e);
|
|
533
|
+
compute(true);
|
|
563
534
|
}
|
|
564
535
|
finally {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
parent.update(key);
|
|
568
|
-
return value;
|
|
569
|
-
}
|
|
536
|
+
local.commit();
|
|
537
|
+
order.set(compute, order.size);
|
|
570
538
|
}
|
|
571
|
-
}
|
|
572
|
-
INFO.set(refresh, key);
|
|
539
|
+
}
|
|
573
540
|
return () => {
|
|
574
|
-
if (
|
|
575
|
-
|
|
576
|
-
|
|
541
|
+
if (!active) {
|
|
542
|
+
active = true;
|
|
543
|
+
source(connect);
|
|
544
|
+
isAsync = true;
|
|
577
545
|
}
|
|
578
|
-
|
|
546
|
+
if (!local)
|
|
547
|
+
parent.waitFor(key);
|
|
548
|
+
if (pending.delete(compute))
|
|
549
|
+
compute();
|
|
550
|
+
return state.get(key);
|
|
579
551
|
};
|
|
580
552
|
}
|
|
581
553
|
const INFO = new WeakMap();
|
|
@@ -598,16 +570,10 @@ function flush(control) {
|
|
|
598
570
|
}
|
|
599
571
|
pending.clear();
|
|
600
572
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
T = getPrototypeOf(T);
|
|
606
|
-
const getter = FindInstruction.get(T);
|
|
607
|
-
if (getter)
|
|
608
|
-
return getter(type, relativeTo, required);
|
|
609
|
-
} while (T.prototype instanceof Model);
|
|
610
|
-
}
|
|
573
|
+
function using(fn) {
|
|
574
|
+
return Object.assign(get.bind(fn), { using });
|
|
575
|
+
}
|
|
576
|
+
get.using = using;
|
|
611
577
|
|
|
612
578
|
const REGISTER = new WeakMap();
|
|
613
579
|
const PENDING = new Map();
|
|
@@ -642,17 +608,17 @@ class Control {
|
|
|
642
608
|
enumerable: false,
|
|
643
609
|
set: this.ref(key),
|
|
644
610
|
get() {
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
if (value === undefined && sub.strict)
|
|
650
|
-
throw suspend(this, key);
|
|
651
|
-
}
|
|
652
|
-
return value;
|
|
611
|
+
const local = subscriber(this);
|
|
612
|
+
return local
|
|
613
|
+
? local.get(key)
|
|
614
|
+
: state.get(key);
|
|
653
615
|
}
|
|
654
616
|
});
|
|
655
617
|
}
|
|
618
|
+
/** Throw suspense which resolves when key is set. */
|
|
619
|
+
waitFor(key) {
|
|
620
|
+
throw suspend(this, key);
|
|
621
|
+
}
|
|
656
622
|
addListener(listener) {
|
|
657
623
|
this.followers.add(listener);
|
|
658
624
|
return () => {
|
|
@@ -738,46 +704,72 @@ function control(subject, cb) {
|
|
|
738
704
|
return cb ? cb(control) : control;
|
|
739
705
|
}
|
|
740
706
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
const
|
|
764
|
-
if (
|
|
765
|
-
local.
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
707
|
+
const Parent = new WeakMap();
|
|
708
|
+
const Oops$3 = issues({
|
|
709
|
+
BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
|
|
710
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
711
|
+
});
|
|
712
|
+
function getParent(from, type) {
|
|
713
|
+
const value = Parent.get(from);
|
|
714
|
+
if (value && type && !(value instanceof type))
|
|
715
|
+
throw Oops$3.Unexpected(type.name, from, value);
|
|
716
|
+
return value;
|
|
717
|
+
}
|
|
718
|
+
function getRecursive(key, from) {
|
|
719
|
+
const context = new WeakMap();
|
|
720
|
+
const { state } = from;
|
|
721
|
+
return (local) => {
|
|
722
|
+
if (!local)
|
|
723
|
+
return state.get(key);
|
|
724
|
+
if (!context.has(local)) {
|
|
725
|
+
let reset;
|
|
726
|
+
const init = () => {
|
|
727
|
+
if (reset)
|
|
728
|
+
reset();
|
|
729
|
+
const value = state.get(key);
|
|
730
|
+
if (value && controller(value)) {
|
|
731
|
+
const child = new Subscriber(value, local.onUpdate);
|
|
732
|
+
if (local.active)
|
|
733
|
+
child.commit();
|
|
734
|
+
local.dependant.add(child);
|
|
735
|
+
context.set(local, child.proxy);
|
|
736
|
+
reset = () => {
|
|
737
|
+
child.release();
|
|
738
|
+
local.dependant.delete(child);
|
|
739
|
+
context.set(local, undefined);
|
|
740
|
+
reset = undefined;
|
|
741
|
+
};
|
|
776
742
|
}
|
|
777
|
-
}
|
|
778
|
-
|
|
743
|
+
};
|
|
744
|
+
local.follow(key, init);
|
|
745
|
+
init();
|
|
746
|
+
}
|
|
747
|
+
return context.get(local);
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
function setRecursive(controller, key, initial) {
|
|
751
|
+
const { state, subject } = controller;
|
|
752
|
+
const Type = initial.constructor;
|
|
753
|
+
let get;
|
|
754
|
+
const onUpdate = (next) => {
|
|
755
|
+
state.set(key, next);
|
|
756
|
+
if (!(next instanceof Type))
|
|
757
|
+
throw Oops$3.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
758
|
+
get = getRecursive(key, controller);
|
|
759
|
+
Parent.set(next, subject);
|
|
760
|
+
control(next);
|
|
761
|
+
return true;
|
|
762
|
+
};
|
|
763
|
+
onUpdate(initial);
|
|
764
|
+
defineProperty(subject, key, {
|
|
765
|
+
set: controller.ref(key, onUpdate),
|
|
766
|
+
get() {
|
|
767
|
+
const local = subscriber(this);
|
|
768
|
+
if (local)
|
|
769
|
+
local.follow(key);
|
|
770
|
+
return get(local);
|
|
771
|
+
}
|
|
779
772
|
});
|
|
780
|
-
return placeholder;
|
|
781
773
|
}
|
|
782
774
|
|
|
783
775
|
/******************************************************************************
|
|
@@ -805,7 +797,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
805
797
|
});
|
|
806
798
|
}
|
|
807
799
|
|
|
808
|
-
const Oops$
|
|
800
|
+
const Oops$2 = issues({
|
|
809
801
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
810
802
|
});
|
|
811
803
|
function run(task) {
|
|
@@ -813,7 +805,7 @@ function run(task) {
|
|
|
813
805
|
let pending = false;
|
|
814
806
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
815
807
|
if (pending)
|
|
816
|
-
return Promise.reject(Oops$
|
|
808
|
+
return Promise.reject(Oops$2.DuplicatePending(key));
|
|
817
809
|
pending = true;
|
|
818
810
|
this.update(key);
|
|
819
811
|
try {
|
|
@@ -866,7 +858,7 @@ function createRef(src, key, cb) {
|
|
|
866
858
|
return refObjectFunction;
|
|
867
859
|
}
|
|
868
860
|
|
|
869
|
-
const Oops$
|
|
861
|
+
const Oops$1 = issues({
|
|
870
862
|
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
871
863
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
872
864
|
});
|
|
@@ -900,7 +892,7 @@ function set(value, argument) {
|
|
|
900
892
|
const suspend = () => {
|
|
901
893
|
if (required === false)
|
|
902
894
|
return undefined;
|
|
903
|
-
const issue = Oops$
|
|
895
|
+
const issue = Oops$1.NotReady(subject, key);
|
|
904
896
|
assign(pending, {
|
|
905
897
|
message: issue.message,
|
|
906
898
|
stack: issue.stack
|
|
@@ -917,7 +909,7 @@ function set(value, argument) {
|
|
|
917
909
|
};
|
|
918
910
|
}
|
|
919
911
|
catch (err) {
|
|
920
|
-
Oops$
|
|
912
|
+
Oops$1.ComputeFailed(subject, key).warn();
|
|
921
913
|
throw err;
|
|
922
914
|
}
|
|
923
915
|
};
|
|
@@ -936,7 +928,7 @@ function set(value, argument) {
|
|
|
936
928
|
if (state.has(key))
|
|
937
929
|
return state.get(key);
|
|
938
930
|
else
|
|
939
|
-
|
|
931
|
+
this.waitFor(key);
|
|
940
932
|
},
|
|
941
933
|
set: typeof argument == "function"
|
|
942
934
|
? createValueEffect(argument)
|
|
@@ -1093,7 +1085,7 @@ function createProxy(emit, watch) {
|
|
|
1093
1085
|
};
|
|
1094
1086
|
}
|
|
1095
1087
|
|
|
1096
|
-
const Oops
|
|
1088
|
+
const Oops = issues({
|
|
1097
1089
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1098
1090
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1099
1091
|
});
|
|
@@ -1109,7 +1101,7 @@ function use(input, argument) {
|
|
|
1109
1101
|
input = new input();
|
|
1110
1102
|
}
|
|
1111
1103
|
else if (input && typeof input !== "object")
|
|
1112
|
-
throw Oops
|
|
1104
|
+
throw Oops.BadArgument(typeof input);
|
|
1113
1105
|
if (input instanceof Map || input instanceof Set)
|
|
1114
1106
|
return keyed(this, key, input);
|
|
1115
1107
|
const onUpdate = (next) => {
|
|
@@ -1126,7 +1118,7 @@ function use(input, argument) {
|
|
|
1126
1118
|
const suspend = () => {
|
|
1127
1119
|
if (required === false)
|
|
1128
1120
|
return;
|
|
1129
|
-
const issue = Oops
|
|
1121
|
+
const issue = Oops.NotReady(subject, key);
|
|
1130
1122
|
assign(pending, {
|
|
1131
1123
|
message: issue.message,
|
|
1132
1124
|
stack: issue.stack
|
|
@@ -1171,6 +1163,42 @@ function use(input, argument) {
|
|
|
1171
1163
|
});
|
|
1172
1164
|
}
|
|
1173
1165
|
|
|
1166
|
+
const LOCAL = "$debug local";
|
|
1167
|
+
const STATE = "$debug state";
|
|
1168
|
+
const UPDATE = "$debug update";
|
|
1169
|
+
const CONTROL = "$debug controller";
|
|
1170
|
+
defineProperties(Model.prototype, {
|
|
1171
|
+
[CONTROL]: {
|
|
1172
|
+
get() {
|
|
1173
|
+
return controller(this);
|
|
1174
|
+
}
|
|
1175
|
+
},
|
|
1176
|
+
[LOCAL]: {
|
|
1177
|
+
get() {
|
|
1178
|
+
return subscriber(this);
|
|
1179
|
+
}
|
|
1180
|
+
},
|
|
1181
|
+
[STATE]: {
|
|
1182
|
+
get() {
|
|
1183
|
+
const { state } = controller(this);
|
|
1184
|
+
const output = {};
|
|
1185
|
+
state.forEach((value, key) => output[key] = value);
|
|
1186
|
+
return output;
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
[UPDATE]: {
|
|
1190
|
+
get() {
|
|
1191
|
+
return (subscriber(this) || controller(this)).latest;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
const Debug = {
|
|
1196
|
+
CONTROL,
|
|
1197
|
+
LOCAL,
|
|
1198
|
+
STATE,
|
|
1199
|
+
UPDATE
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1174
1202
|
class Register {
|
|
1175
1203
|
constructor() {
|
|
1176
1204
|
this.table = new Map();
|
|
@@ -1226,384 +1254,12 @@ class Register {
|
|
|
1226
1254
|
delete this[key];
|
|
1227
1255
|
}
|
|
1228
1256
|
for (const model of items)
|
|
1229
|
-
model.
|
|
1230
|
-
}
|
|
1231
|
-
delete(instance) {
|
|
1232
|
-
for (const key of getOwnPropertySymbols(this)) {
|
|
1233
|
-
const entry = getOwnPropertyDescriptor(this, key);
|
|
1234
|
-
if (entry.value === instance)
|
|
1235
|
-
delete this[key];
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
const Global$1 = new Register();
|
|
1240
|
-
|
|
1241
|
-
const Oops$3 = issues({
|
|
1242
|
-
AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`,
|
|
1243
|
-
DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.new() before attempting to access, or consider using ${name}.use() instead.`,
|
|
1244
|
-
NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
|
|
1245
|
-
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined by same Provider.`
|
|
1246
|
-
});
|
|
1247
|
-
const LookupContext = React.createContext(Global$1);
|
|
1248
|
-
function useLookup() {
|
|
1249
|
-
try {
|
|
1250
|
-
return React.useContext(LookupContext);
|
|
1251
|
-
}
|
|
1252
|
-
catch (err) {
|
|
1253
|
-
return Global$1;
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
function useContext(Type, required) {
|
|
1257
|
-
const instance = useLookup().get(Type);
|
|
1258
|
-
if (instance === null)
|
|
1259
|
-
throw Oops$3.MultipleExist(Type.name);
|
|
1260
|
-
if (!instance && required !== false)
|
|
1261
|
-
throw MVC.isTypeof(Type) && Type.global
|
|
1262
|
-
? Oops$3.DoesNotExist(Type.name)
|
|
1263
|
-
: Oops$3.NotFound(Type.name);
|
|
1264
|
-
return instance;
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
const Oops$2 = issues({
|
|
1268
|
-
NotAllowed: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
1269
|
-
AmbientRequired: (requested, requester) => `Attempted to find an instance of ${requested} in context. It is required by ${requester}, but one could not be found.`
|
|
1270
|
-
});
|
|
1271
|
-
const Pending = new WeakMap();
|
|
1272
|
-
const Applied = new WeakMap();
|
|
1273
|
-
function getContextForGetInstruction(type, relativeTo, required) {
|
|
1274
|
-
let item = getParent(type, relativeTo);
|
|
1275
|
-
return (refresh) => {
|
|
1276
|
-
if (item)
|
|
1277
|
-
return item;
|
|
1278
|
-
findRelative(relativeTo, type, got => {
|
|
1279
|
-
if (got) {
|
|
1280
|
-
item = got;
|
|
1281
|
-
refresh(got);
|
|
1282
|
-
}
|
|
1283
|
-
else if (required)
|
|
1284
|
-
throw Oops$2.AmbientRequired(type.name, relativeTo);
|
|
1285
|
-
});
|
|
1286
|
-
};
|
|
1287
|
-
}
|
|
1288
|
-
function findRelative(from, type, callback) {
|
|
1289
|
-
if (MVC.isTypeof(type) && type.global)
|
|
1290
|
-
callback(Global$1.get(type));
|
|
1291
|
-
else if (from.constructor.global)
|
|
1292
|
-
throw Oops$2.NotAllowed(from, type.name);
|
|
1293
|
-
else
|
|
1294
|
-
getPending(from).push(context => {
|
|
1295
|
-
callback(context.get(type));
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
function usePeerContext(subject) {
|
|
1299
|
-
if (Applied.has(subject)) {
|
|
1300
|
-
if (Applied.get(subject))
|
|
1301
|
-
useLookup();
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
const pending = Pending.get(subject);
|
|
1305
|
-
if (pending) {
|
|
1306
|
-
const local = useLookup();
|
|
1307
|
-
for (const init of pending)
|
|
1308
|
-
init(local);
|
|
1309
|
-
Pending.delete(subject);
|
|
1310
|
-
}
|
|
1311
|
-
Applied.set(subject, !!pending);
|
|
1312
|
-
}
|
|
1313
|
-
function getPending(subject) {
|
|
1314
|
-
let pending = Pending.get(subject);
|
|
1315
|
-
if (!pending)
|
|
1316
|
-
Pending.set(subject, pending = []);
|
|
1317
|
-
return pending;
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
function useModel(source, arg1, arg2) {
|
|
1321
|
-
const instance = React.useMemo(() => {
|
|
1322
|
-
const callback = arg2 || arg1;
|
|
1323
|
-
const instance = Model.isTypeof(source)
|
|
1324
|
-
? new source()
|
|
1325
|
-
: source();
|
|
1326
|
-
control(instance);
|
|
1327
|
-
if (typeof callback == "function")
|
|
1328
|
-
callback(instance);
|
|
1329
|
-
return instance;
|
|
1330
|
-
}, []);
|
|
1331
|
-
usePeerContext(instance);
|
|
1332
|
-
if (Array.isArray(arg1)) {
|
|
1333
|
-
const update = React.useState(0)[1];
|
|
1334
|
-
React.useLayoutEffect(() => {
|
|
1335
|
-
if (arg1.length && instance instanceof Model)
|
|
1336
|
-
instance.on(arg1, () => update(x => x + 1));
|
|
1337
|
-
return () => {
|
|
1338
|
-
if (Model.isTypeof(source))
|
|
1339
|
-
instance.end();
|
|
1340
|
-
};
|
|
1341
|
-
}, []);
|
|
1342
|
-
return instance;
|
|
1343
|
-
}
|
|
1344
|
-
const state = React.useState(0);
|
|
1345
|
-
const local = React.useMemo(() => {
|
|
1346
|
-
const refresh = state[1].bind(null, x => x + 1);
|
|
1347
|
-
return new Subscriber(control(instance), () => refresh);
|
|
1348
|
-
}, []);
|
|
1349
|
-
if (typeof arg1 == "object")
|
|
1350
|
-
local.apply(arg1, arg2);
|
|
1351
|
-
React.useLayoutEffect(() => {
|
|
1352
|
-
local.commit();
|
|
1353
|
-
return () => {
|
|
1354
|
-
local.release();
|
|
1355
|
-
if (Model.isTypeof(source))
|
|
1356
|
-
instance.end();
|
|
1357
|
-
};
|
|
1358
|
-
}, []);
|
|
1359
|
-
return local.proxy;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
function useTap(source, arg1, arg2) {
|
|
1363
|
-
const instance = typeof source == "object"
|
|
1364
|
-
? source
|
|
1365
|
-
: "get" in source
|
|
1366
|
-
? source.get()
|
|
1367
|
-
: source();
|
|
1368
|
-
const deps = [uid(instance)];
|
|
1369
|
-
const state = React.useState(0);
|
|
1370
|
-
const local = React.useMemo(() => {
|
|
1371
|
-
const refresh = state[1].bind(null, x => x + 1);
|
|
1372
|
-
const controller = control(instance);
|
|
1373
|
-
if (typeof arg1 != "function")
|
|
1374
|
-
return new Subscriber(controller, () => refresh, arg1);
|
|
1375
|
-
const sub = new Subscriber(controller, () => update);
|
|
1376
|
-
const spy = sub.proxy;
|
|
1377
|
-
let make = () => arg1.call(spy, spy, forceUpdate);
|
|
1378
|
-
function forceUpdate(passthru) {
|
|
1379
|
-
if (typeof passthru == "function")
|
|
1380
|
-
passthru = passthru();
|
|
1381
|
-
if (make)
|
|
1382
|
-
reassign(make());
|
|
1383
|
-
else
|
|
1384
|
-
refresh();
|
|
1385
|
-
if (passthru)
|
|
1386
|
-
return passthru.finally(refresh);
|
|
1387
|
-
}
|
|
1388
|
-
function reassign(next) {
|
|
1389
|
-
value = next;
|
|
1390
|
-
if (retry) {
|
|
1391
|
-
retry();
|
|
1392
|
-
retry = undefined;
|
|
1393
|
-
}
|
|
1394
|
-
else
|
|
1395
|
-
refresh();
|
|
1396
|
-
}
|
|
1397
|
-
let retry;
|
|
1398
|
-
let update;
|
|
1399
|
-
let value = make();
|
|
1400
|
-
if (value === null) {
|
|
1401
|
-
sub.watch.clear();
|
|
1402
|
-
make = undefined;
|
|
1403
|
-
return;
|
|
1404
|
-
}
|
|
1405
|
-
if (typeof value == "function") {
|
|
1406
|
-
const get = value;
|
|
1407
|
-
sub.watch.clear();
|
|
1408
|
-
arg1 = () => get();
|
|
1409
|
-
value = get();
|
|
1410
|
-
}
|
|
1411
|
-
if (value instanceof Promise) {
|
|
1412
|
-
value.then(reassign);
|
|
1413
|
-
value = undefined;
|
|
1414
|
-
}
|
|
1415
|
-
else {
|
|
1416
|
-
sub.commit();
|
|
1417
|
-
update = () => {
|
|
1418
|
-
const next = make();
|
|
1419
|
-
if (notEqual(value, next))
|
|
1420
|
-
reassign(next);
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1423
|
-
defineProperty(sub, "proxy", {
|
|
1424
|
-
get() {
|
|
1425
|
-
if (value !== undefined)
|
|
1426
|
-
return value;
|
|
1427
|
-
if (arg2)
|
|
1428
|
-
throw new Promise(res => retry = res);
|
|
1429
|
-
return null;
|
|
1430
|
-
}
|
|
1431
|
-
});
|
|
1432
|
-
return sub;
|
|
1433
|
-
}, deps);
|
|
1434
|
-
if (!local)
|
|
1435
|
-
return null;
|
|
1436
|
-
React.useLayoutEffect(() => {
|
|
1437
|
-
local.commit();
|
|
1438
|
-
return () => local.release();
|
|
1439
|
-
}, deps);
|
|
1440
|
-
return local.proxy;
|
|
1441
|
-
}
|
|
1442
|
-
/** Values are not equal for purposes of a refresh. */
|
|
1443
|
-
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
1444
|
-
!Array.isArray(b) ||
|
|
1445
|
-
a.length !== b.length ||
|
|
1446
|
-
a.some((x, i) => x !== b[i])));
|
|
1447
|
-
|
|
1448
|
-
class MVC extends Model {
|
|
1449
|
-
end(force) {
|
|
1450
|
-
const type = this.constructor;
|
|
1451
|
-
if (type.keepAlive && !force)
|
|
1452
|
-
return false;
|
|
1453
|
-
super.end();
|
|
1454
|
-
Global$1.delete(this);
|
|
1455
|
-
return true;
|
|
1456
|
-
}
|
|
1457
|
-
static new(...args) {
|
|
1458
|
-
const exists = Global$1.get(this);
|
|
1459
|
-
if (exists)
|
|
1460
|
-
if (this.keepAlive)
|
|
1461
|
-
return exists;
|
|
1462
|
-
else
|
|
1463
|
-
throw Oops$3.AlreadyExists(this.name);
|
|
1464
|
-
const instance = super.new(...args);
|
|
1465
|
-
if (this.global)
|
|
1466
|
-
Global$1.add(instance);
|
|
1467
|
-
return instance;
|
|
1468
|
-
}
|
|
1469
|
-
static get(arg1, arg2) {
|
|
1470
|
-
const required = arg1 === undefined || arg1 === true;
|
|
1471
|
-
const instance = useContext(this, required);
|
|
1472
|
-
if (typeof arg1 === "function" && instance)
|
|
1473
|
-
callback(arg1);
|
|
1474
|
-
else if (arg2)
|
|
1475
|
-
callback(arg2);
|
|
1476
|
-
return instance;
|
|
1477
|
-
function callback(effect) {
|
|
1478
|
-
try {
|
|
1479
|
-
React.useLayoutEffect(() => effect(instance), []);
|
|
1480
|
-
}
|
|
1481
|
-
catch (err) {
|
|
1482
|
-
if (instance)
|
|
1483
|
-
instance.on(effect, []);
|
|
1484
|
-
else
|
|
1485
|
-
effect(undefined);
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1257
|
+
model.gc();
|
|
1488
1258
|
}
|
|
1489
|
-
static tap(arg1, arg2) {
|
|
1490
|
-
return useTap(this, arg1, arg2);
|
|
1491
|
-
}
|
|
1492
|
-
static use(a, b) {
|
|
1493
|
-
return useModel(this, a, b);
|
|
1494
|
-
}
|
|
1495
|
-
static meta(arg1, arg2) {
|
|
1496
|
-
return useTap(() => this, arg1, arg2);
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
FindInstruction.set(MVC, getContextForGetInstruction);
|
|
1500
|
-
|
|
1501
|
-
const Oops$1 = issues({
|
|
1502
|
-
BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
|
|
1503
|
-
});
|
|
1504
|
-
function Consumer(props) {
|
|
1505
|
-
const { get, has, children, for: type } = props;
|
|
1506
|
-
if (typeof children == "function")
|
|
1507
|
-
return children(useTap(type));
|
|
1508
|
-
const callback = has || get;
|
|
1509
|
-
if (typeof callback == "function")
|
|
1510
|
-
callback(useContext(type, !!has));
|
|
1511
|
-
else
|
|
1512
|
-
throw Oops$1.BadProps();
|
|
1513
|
-
return null;
|
|
1514
1259
|
}
|
|
1515
1260
|
|
|
1516
|
-
const
|
|
1517
|
-
|
|
1518
|
-
});
|
|
1519
|
-
function Provider(props) {
|
|
1520
|
-
const context = useNewContext(props.for, props.use);
|
|
1521
|
-
return (React.createElement(LookupContext.Provider, { value: context }, props.fallback === false
|
|
1522
|
-
? props.children
|
|
1523
|
-
: (React.createElement(Suspense, { fallback: props.fallback || null }, props.children))));
|
|
1524
|
-
}
|
|
1525
|
-
function useNewContext(include, assign) {
|
|
1526
|
-
const init = new Set();
|
|
1527
|
-
const ambient = useLookup();
|
|
1528
|
-
const context = React.useMemo(() => {
|
|
1529
|
-
if (!include)
|
|
1530
|
-
throw Oops.NoType();
|
|
1531
|
-
return ambient.push();
|
|
1532
|
-
}, []);
|
|
1533
|
-
function register(key, input) {
|
|
1534
|
-
let instance;
|
|
1535
|
-
if (MVC.isTypeof(input) && input.global)
|
|
1536
|
-
instance = input.new();
|
|
1537
|
-
else if (context.register.get(key) === input)
|
|
1538
|
-
instance = typeof input == "object"
|
|
1539
|
-
? input
|
|
1540
|
-
: context.get(input);
|
|
1541
|
-
else
|
|
1542
|
-
instance = context.add(input, key);
|
|
1543
|
-
init.add(instance);
|
|
1544
|
-
if (assign)
|
|
1545
|
-
assignWeak(instance, assign);
|
|
1546
|
-
}
|
|
1547
|
-
if (typeof include == "function" || include instanceof Model)
|
|
1548
|
-
register(0, include);
|
|
1549
|
-
else
|
|
1550
|
-
entries(include).forEach(e => register(...e));
|
|
1551
|
-
for (const instance of init) {
|
|
1552
|
-
control(instance).state.forEach(value => {
|
|
1553
|
-
// TODO: should this run repeatedly?
|
|
1554
|
-
if (Parent.get(value) === instance) {
|
|
1555
|
-
context.add(value);
|
|
1556
|
-
init.add(value);
|
|
1557
|
-
}
|
|
1558
|
-
});
|
|
1559
|
-
for (const apply of getPending(instance))
|
|
1560
|
-
apply(context);
|
|
1561
|
-
// TODO: add test to validate this.
|
|
1562
|
-
init.delete(instance);
|
|
1563
|
-
}
|
|
1564
|
-
React.useLayoutEffect(() => () => context.pop(), []);
|
|
1565
|
-
return context;
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
class Global extends MVC {
|
|
1569
|
-
}
|
|
1570
|
-
Global.global = true;
|
|
1571
|
-
Global.keepAlive = true;
|
|
1572
|
-
|
|
1573
|
-
const LOCAL = "$debug local";
|
|
1574
|
-
const STATE = "$debug state";
|
|
1575
|
-
const UPDATE = "$debug update";
|
|
1576
|
-
const CONTROL = "$debug controller";
|
|
1577
|
-
defineProperties(Model.prototype, {
|
|
1578
|
-
[CONTROL]: {
|
|
1579
|
-
get() {
|
|
1580
|
-
return controller(this);
|
|
1581
|
-
}
|
|
1582
|
-
},
|
|
1583
|
-
[LOCAL]: {
|
|
1584
|
-
get() {
|
|
1585
|
-
return subscriber(this);
|
|
1586
|
-
}
|
|
1587
|
-
},
|
|
1588
|
-
[STATE]: {
|
|
1589
|
-
get() {
|
|
1590
|
-
const { state } = controller(this);
|
|
1591
|
-
const output = {};
|
|
1592
|
-
state.forEach((value, key) => output[key] = value);
|
|
1593
|
-
return output;
|
|
1594
|
-
}
|
|
1595
|
-
},
|
|
1596
|
-
[UPDATE]: {
|
|
1597
|
-
get() {
|
|
1598
|
-
return (subscriber(this) || controller(this)).latest;
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
});
|
|
1602
|
-
const Debug = {
|
|
1603
|
-
CONTROL,
|
|
1604
|
-
LOCAL,
|
|
1605
|
-
STATE,
|
|
1606
|
-
UPDATE
|
|
1261
|
+
const Internal = {
|
|
1262
|
+
getParent
|
|
1607
1263
|
};
|
|
1608
1264
|
|
|
1609
|
-
export {
|
|
1265
|
+
export { Control, Debug, Internal, Model, Register, Subscriber, add, get, ref, run, set, use };
|