@expressive/mvc 1.0.0-beta.9 → 1.0.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 +594 -0
- package/lib/index.esm.js +1606 -0
- package/lib/index.js +1498 -881
- package/package.json +20 -22
- package/types/context.d.ts +0 -59
- package/types/dispatch.d.ts +0 -55
- package/types/index.d.ts +0 -9
- package/types/instructions.d.ts +0 -101
- package/types/lifecycle.d.ts +0 -30
- package/types/model.d.ts +0 -421
- package/types/selector.ts +0 -29
- package/types/types.d.ts +0 -14
package/lib/index.esm.js
ADDED
|
@@ -0,0 +1,1606 @@
|
|
|
1
|
+
import React, { useState, Suspense } from 'react';
|
|
2
|
+
|
|
3
|
+
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
4
|
+
const UID_CACHE = new WeakMap();
|
|
5
|
+
function assignWeak(into, from) {
|
|
6
|
+
for (const K in from)
|
|
7
|
+
if (K in into)
|
|
8
|
+
into[K] = from[K];
|
|
9
|
+
}
|
|
10
|
+
function uid(object) {
|
|
11
|
+
let uid = UID_CACHE.get(object);
|
|
12
|
+
if (!uid)
|
|
13
|
+
UID_CACHE.set(object, uid = Math.random());
|
|
14
|
+
return uid;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class Issue extends Error {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(...arguments);
|
|
20
|
+
// drop first line (error factory) in stack trace.
|
|
21
|
+
this.stack = this.stack.replace(/\n.+/, "");
|
|
22
|
+
}
|
|
23
|
+
warn() {
|
|
24
|
+
console.warn(this.message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function issues(register) {
|
|
28
|
+
const Library = {};
|
|
29
|
+
for (const name in register)
|
|
30
|
+
Library[name] = (...args) => new Issue(register[name].apply(null, args));
|
|
31
|
+
return Library;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const Oops$f = issues({
|
|
35
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
36
|
+
});
|
|
37
|
+
function suspend(source, key) {
|
|
38
|
+
const error = Oops$f.NotReady(source.subject, key);
|
|
39
|
+
const promise = new Promise(resolve => {
|
|
40
|
+
const release = source.addListener(forKey => {
|
|
41
|
+
if (forKey == key)
|
|
42
|
+
return () => {
|
|
43
|
+
if (source.state.get(key) !== undefined) {
|
|
44
|
+
release();
|
|
45
|
+
resolve();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
return assign(promise, {
|
|
51
|
+
toString: () => String(error),
|
|
52
|
+
name: "Suspense",
|
|
53
|
+
message: error.message,
|
|
54
|
+
stack: error.stack
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function mayRetry(fn) {
|
|
58
|
+
const retry = (err) => {
|
|
59
|
+
if (err instanceof Promise)
|
|
60
|
+
return err.then(compute);
|
|
61
|
+
else
|
|
62
|
+
throw err;
|
|
63
|
+
};
|
|
64
|
+
const compute = () => {
|
|
65
|
+
try {
|
|
66
|
+
const output = fn();
|
|
67
|
+
return output instanceof Promise
|
|
68
|
+
? output.catch(retry)
|
|
69
|
+
: output;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return retry(err);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return compute();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const Oops$e = issues({
|
|
79
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
80
|
+
});
|
|
81
|
+
const INFO = new WeakMap();
|
|
82
|
+
const KEYS = new WeakMap();
|
|
83
|
+
const ORDER = new WeakMap();
|
|
84
|
+
function computeMode(self, source, setter, key, required) {
|
|
85
|
+
const { subject, state } = self;
|
|
86
|
+
let sub;
|
|
87
|
+
let order = ORDER.get(self);
|
|
88
|
+
let pending = KEYS.get(self);
|
|
89
|
+
if (!order)
|
|
90
|
+
ORDER.set(self, order = new Map());
|
|
91
|
+
if (!pending)
|
|
92
|
+
KEYS.set(self, pending = new Set());
|
|
93
|
+
const compute = (initial) => {
|
|
94
|
+
try {
|
|
95
|
+
return setter.call(sub.proxy, sub.proxy);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
Oops$e.Failed(subject, key, initial).warn();
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const refresh = () => {
|
|
103
|
+
let value;
|
|
104
|
+
try {
|
|
105
|
+
value = compute(false);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
console.error(e);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
if (state.get(key) !== value) {
|
|
112
|
+
state.set(key, value);
|
|
113
|
+
self.update(key);
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const create = () => {
|
|
119
|
+
sub = source.subscribe((_, source) => {
|
|
120
|
+
if (source !== self)
|
|
121
|
+
refresh();
|
|
122
|
+
else
|
|
123
|
+
pending.add(refresh);
|
|
124
|
+
});
|
|
125
|
+
sub.watch.set(key, false);
|
|
126
|
+
try {
|
|
127
|
+
const value = compute(true);
|
|
128
|
+
state.set(key, value);
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
throw e;
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
sub.commit();
|
|
136
|
+
order.set(refresh, order.size);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
INFO.set(refresh, key);
|
|
140
|
+
return () => {
|
|
141
|
+
if (pending.has(refresh)) {
|
|
142
|
+
pending.delete(refresh);
|
|
143
|
+
refresh();
|
|
144
|
+
}
|
|
145
|
+
const value = sub ? state.get(key) : create();
|
|
146
|
+
if (value === undefined && required)
|
|
147
|
+
throw suspend(self, key);
|
|
148
|
+
return value;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function flush(control) {
|
|
152
|
+
const pending = KEYS.get(control);
|
|
153
|
+
if (!pending || !pending.size)
|
|
154
|
+
return;
|
|
155
|
+
const priority = ORDER.get(control);
|
|
156
|
+
while (pending.size) {
|
|
157
|
+
let compute;
|
|
158
|
+
for (const item of pending)
|
|
159
|
+
if (!compute || priority.get(item) < priority.get(compute))
|
|
160
|
+
compute = item;
|
|
161
|
+
pending.delete(compute);
|
|
162
|
+
const key = INFO.get(compute);
|
|
163
|
+
if (!control.frame.has(key))
|
|
164
|
+
compute();
|
|
165
|
+
}
|
|
166
|
+
pending.clear();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const Oops$d = issues({
|
|
170
|
+
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
171
|
+
});
|
|
172
|
+
function createEffect(model, callback, keys) {
|
|
173
|
+
return control(model, controller => {
|
|
174
|
+
let unSet;
|
|
175
|
+
let busy = false;
|
|
176
|
+
function effect(value) {
|
|
177
|
+
if (typeof unSet == "function")
|
|
178
|
+
unSet();
|
|
179
|
+
unSet = callback.call(this, value);
|
|
180
|
+
if (unSet instanceof Promise)
|
|
181
|
+
unSet = undefined;
|
|
182
|
+
if (unSet && typeof unSet !== "function")
|
|
183
|
+
throw Oops$d.BadCallback();
|
|
184
|
+
}
|
|
185
|
+
function invoke() {
|
|
186
|
+
if (busy)
|
|
187
|
+
return;
|
|
188
|
+
const output = mayRetry(() => {
|
|
189
|
+
effect.call(model, model);
|
|
190
|
+
});
|
|
191
|
+
if (output instanceof Promise) {
|
|
192
|
+
output.finally(() => busy = false);
|
|
193
|
+
busy = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (Array.isArray(keys)) {
|
|
197
|
+
invoke();
|
|
198
|
+
return controller.addListener(key => {
|
|
199
|
+
if (key === null) {
|
|
200
|
+
if (!keys.length)
|
|
201
|
+
invoke();
|
|
202
|
+
}
|
|
203
|
+
else if (keys.includes(key))
|
|
204
|
+
return invoke;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
const sub = controller.subscribe(() => invoke);
|
|
208
|
+
model = sub.proxy;
|
|
209
|
+
invoke();
|
|
210
|
+
return sub.commit();
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function createValueEffect(callback) {
|
|
214
|
+
let unSet;
|
|
215
|
+
return function (value) {
|
|
216
|
+
if (typeof unSet == "function")
|
|
217
|
+
unSet(value);
|
|
218
|
+
const out = callback.call(this, value, this);
|
|
219
|
+
if (typeof out == "boolean")
|
|
220
|
+
return out;
|
|
221
|
+
if (!out || out instanceof Promise)
|
|
222
|
+
return;
|
|
223
|
+
if (typeof out == "function")
|
|
224
|
+
unSet = out;
|
|
225
|
+
else
|
|
226
|
+
throw Oops$d.BadCallback();
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const Oops$c = issues({
|
|
231
|
+
Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
|
|
232
|
+
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
233
|
+
StrictUpdate: () => `Expected update but none in progress.`,
|
|
234
|
+
StrictNoUpdate: () => `Update is not expected but one is in progress!`
|
|
235
|
+
});
|
|
236
|
+
function addEventListener(source, arg1, arg2, arg3) {
|
|
237
|
+
if (typeof arg1 == "string")
|
|
238
|
+
arg1 = [arg1];
|
|
239
|
+
return control(source, controller => {
|
|
240
|
+
for (const key of arg1)
|
|
241
|
+
try {
|
|
242
|
+
void source[key];
|
|
243
|
+
}
|
|
244
|
+
catch (e) { }
|
|
245
|
+
const removeListener = controller.addListener(key => {
|
|
246
|
+
if (!key && !arg1.length)
|
|
247
|
+
arg2.call(source, []);
|
|
248
|
+
if (arg1.includes(key)) {
|
|
249
|
+
if (arg3)
|
|
250
|
+
removeListener();
|
|
251
|
+
return arg2.bind(source);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
return removeListener;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function awaitUpdate(source, arg1, arg2) {
|
|
258
|
+
const single = typeof arg1 == "string";
|
|
259
|
+
const keys = typeof arg1 == "string" ? [arg1] :
|
|
260
|
+
typeof arg1 == "object" ? arg1 :
|
|
261
|
+
undefined;
|
|
262
|
+
return new Promise((resolve, reject) => {
|
|
263
|
+
const timeout = (message) => {
|
|
264
|
+
const k = keys ? keys.join(", ") : "any";
|
|
265
|
+
removeListener();
|
|
266
|
+
reject(Oops$c.Timeout(k, message));
|
|
267
|
+
};
|
|
268
|
+
const removeListener = control(source, controller => {
|
|
269
|
+
const pending = controller.frame;
|
|
270
|
+
if (keys === null) {
|
|
271
|
+
if (pending.size)
|
|
272
|
+
reject(Oops$c.StrictNoUpdate());
|
|
273
|
+
else
|
|
274
|
+
resolve(null);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (keys) {
|
|
278
|
+
if (keys.length) {
|
|
279
|
+
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
280
|
+
reject(Oops$c.KeysExpected(keys[0]));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
for (const key of keys)
|
|
285
|
+
try {
|
|
286
|
+
void source[key];
|
|
287
|
+
}
|
|
288
|
+
catch (e) { }
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
292
|
+
reject(Oops$c.StrictUpdate());
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
else
|
|
296
|
+
controller.waiting.add(resolve);
|
|
297
|
+
return controller.addListener(key => {
|
|
298
|
+
if (!key) {
|
|
299
|
+
if (keys && !keys.length)
|
|
300
|
+
resolve([]);
|
|
301
|
+
else
|
|
302
|
+
timeout(`lifetime of ${source}`);
|
|
303
|
+
}
|
|
304
|
+
else if (!keys || keys.includes(key)) {
|
|
305
|
+
removeListener();
|
|
306
|
+
return keys => resolve(single ? controller.state.get(key) : keys);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
if (arg2 && typeof arg2 == "number")
|
|
311
|
+
setTimeout(() => timeout(`${arg2}ms`), arg2);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const REGISTER$1 = new WeakMap();
|
|
316
|
+
class Subscriber {
|
|
317
|
+
constructor(parent, onUpdate) {
|
|
318
|
+
this.parent = parent;
|
|
319
|
+
this.onUpdate = onUpdate;
|
|
320
|
+
this.active = false;
|
|
321
|
+
this.dependant = new Set();
|
|
322
|
+
this.watch = new Map();
|
|
323
|
+
const proxy = create(parent.subject);
|
|
324
|
+
const reset = () => this.latest = undefined;
|
|
325
|
+
REGISTER$1.set(proxy, this);
|
|
326
|
+
defineProperty(this, "proxy", {
|
|
327
|
+
configurable: true,
|
|
328
|
+
get() {
|
|
329
|
+
setTimeout(reset, 0);
|
|
330
|
+
return proxy;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
get using() {
|
|
335
|
+
return Array.from(this.watch.keys());
|
|
336
|
+
}
|
|
337
|
+
add(key, value) {
|
|
338
|
+
if (value !== undefined)
|
|
339
|
+
this.watch.set(key, value);
|
|
340
|
+
else if (!this.watch.has(key))
|
|
341
|
+
this.watch.set(key, true);
|
|
342
|
+
}
|
|
343
|
+
commit() {
|
|
344
|
+
const release = this.parent.addListener(key => {
|
|
345
|
+
if (this.active)
|
|
346
|
+
this.onEvent(key);
|
|
347
|
+
});
|
|
348
|
+
this.active = true;
|
|
349
|
+
this.dependant.forEach(x => x.commit());
|
|
350
|
+
return this.release = () => {
|
|
351
|
+
this.dependant.forEach(x => x.release());
|
|
352
|
+
release();
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
onEvent(key) {
|
|
356
|
+
const { parent, watch } = this;
|
|
357
|
+
let handler = watch.get(key);
|
|
358
|
+
if (typeof handler == "function")
|
|
359
|
+
handler = handler();
|
|
360
|
+
if (handler) {
|
|
361
|
+
const notify = this.onUpdate(key, parent);
|
|
362
|
+
if (notify) {
|
|
363
|
+
parent.waiting.add(update => {
|
|
364
|
+
this.latest = update.filter(k => watch.has(k));
|
|
365
|
+
});
|
|
366
|
+
parent.waiting.add(notify);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function subscriber(from) {
|
|
372
|
+
return REGISTER$1.get(from);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const Oops$b = issues({
|
|
376
|
+
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
377
|
+
});
|
|
378
|
+
class Model {
|
|
379
|
+
constructor() {
|
|
380
|
+
new Control(this);
|
|
381
|
+
defineProperty(this, "is", { value: this });
|
|
382
|
+
}
|
|
383
|
+
on(arg1, arg2, arg3) {
|
|
384
|
+
if (typeof arg1 == "function")
|
|
385
|
+
return createEffect(this.is, arg1, arg2);
|
|
386
|
+
if (typeof arg2 != "function")
|
|
387
|
+
return awaitUpdate(this.is, arg1, arg2);
|
|
388
|
+
if (arg1)
|
|
389
|
+
return addEventListener(this.is, arg1, arg2, arg3);
|
|
390
|
+
}
|
|
391
|
+
get(arg1, arg2) {
|
|
392
|
+
const { state } = control(this);
|
|
393
|
+
const extract = typeof arg1 == "string"
|
|
394
|
+
? () => state.get(arg1)
|
|
395
|
+
: () => {
|
|
396
|
+
const output = {};
|
|
397
|
+
for (const key of arg1 || state.keys())
|
|
398
|
+
output[key] = state.get(key);
|
|
399
|
+
return output;
|
|
400
|
+
};
|
|
401
|
+
if (!arg1 || arg2 === undefined)
|
|
402
|
+
return extract();
|
|
403
|
+
if (typeof arg2 == "function")
|
|
404
|
+
return this.on(arg1, () => arg2(extract()));
|
|
405
|
+
const timeout = typeof arg2 == "number" ? arg2 : undefined;
|
|
406
|
+
return this.on(arg1, timeout).then(extract);
|
|
407
|
+
}
|
|
408
|
+
set(arg1, arg2) {
|
|
409
|
+
const controller = control(this);
|
|
410
|
+
const { state } = controller;
|
|
411
|
+
if (typeof arg1 == "object")
|
|
412
|
+
for (const key in arg1) {
|
|
413
|
+
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
414
|
+
state.set(key, arg1[key]);
|
|
415
|
+
controller.update(key);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else if (typeof arg1 == "string") {
|
|
419
|
+
controller.update(arg1);
|
|
420
|
+
if (1 in arguments) {
|
|
421
|
+
if (state.has(arg1))
|
|
422
|
+
state.set(arg1, arg2);
|
|
423
|
+
else if (arg1 in this) {
|
|
424
|
+
const method = this[arg1];
|
|
425
|
+
if (typeof method == "function")
|
|
426
|
+
method.call(this, arg2);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
then: (callback) => {
|
|
432
|
+
if (!callback)
|
|
433
|
+
throw Oops$b.NoChaining();
|
|
434
|
+
controller.waiting.add(callback);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Clean up side effects and mark this instance for garbage-collection.
|
|
440
|
+
*/
|
|
441
|
+
end() {
|
|
442
|
+
control(this).clear();
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Creates a new instance of this controller.
|
|
446
|
+
*
|
|
447
|
+
* Beyond `new this(...)`, method will activate managed-state.
|
|
448
|
+
*
|
|
449
|
+
* @param args - arguments sent to constructor
|
|
450
|
+
*/
|
|
451
|
+
static new(...args) {
|
|
452
|
+
const instance = new this(...args);
|
|
453
|
+
control(instance);
|
|
454
|
+
return instance;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Static equivalent of `x instanceof this`.
|
|
458
|
+
*
|
|
459
|
+
* Will determine if provided class is a subtype of this one.
|
|
460
|
+
*/
|
|
461
|
+
static isTypeof(maybe) {
|
|
462
|
+
return (typeof maybe == "function" &&
|
|
463
|
+
maybe.prototype instanceof this);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
defineProperty(Model.prototype, "toString", {
|
|
467
|
+
value() {
|
|
468
|
+
return this.constructor.name;
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const REGISTER = new WeakMap();
|
|
473
|
+
const PENDING = new Map();
|
|
474
|
+
class Control {
|
|
475
|
+
constructor(subject) {
|
|
476
|
+
this.subject = subject;
|
|
477
|
+
this.frame = new Set();
|
|
478
|
+
this.waiting = new Set();
|
|
479
|
+
this.followers = new Set();
|
|
480
|
+
REGISTER.set(subject, this);
|
|
481
|
+
}
|
|
482
|
+
subscribe(callback) {
|
|
483
|
+
return new Subscriber(this, callback);
|
|
484
|
+
}
|
|
485
|
+
watch(key) {
|
|
486
|
+
const { subject, state } = this;
|
|
487
|
+
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
488
|
+
if (typeof value == "function")
|
|
489
|
+
return;
|
|
490
|
+
if (typeof value == "symbol") {
|
|
491
|
+
const instruction = PENDING.get(value);
|
|
492
|
+
if (instruction) {
|
|
493
|
+
delete subject[key];
|
|
494
|
+
PENDING.delete(value);
|
|
495
|
+
instruction.call(this, key, this);
|
|
496
|
+
}
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
state.set(key, value);
|
|
500
|
+
if (value instanceof Model) {
|
|
501
|
+
setRecursive(this, key, value);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
defineProperty(subject, key, {
|
|
505
|
+
enumerable: false,
|
|
506
|
+
set: this.ref(key),
|
|
507
|
+
get() {
|
|
508
|
+
const sub = subscriber(this);
|
|
509
|
+
if (sub)
|
|
510
|
+
sub.add(key);
|
|
511
|
+
return state.get(key);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
addListener(listener) {
|
|
516
|
+
this.followers.add(listener);
|
|
517
|
+
return () => {
|
|
518
|
+
this.followers.delete(listener);
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
ref(key, handler) {
|
|
522
|
+
const { subject, state } = this;
|
|
523
|
+
return (value) => {
|
|
524
|
+
if (state.get(key) == value)
|
|
525
|
+
return;
|
|
526
|
+
if (handler)
|
|
527
|
+
switch (handler.call(subject, value)) {
|
|
528
|
+
case true:
|
|
529
|
+
this.update(key);
|
|
530
|
+
case false:
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
state.set(key, value);
|
|
534
|
+
this.update(key);
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
update(key) {
|
|
538
|
+
const { followers, frame, waiting } = this;
|
|
539
|
+
if (frame.has(key))
|
|
540
|
+
return;
|
|
541
|
+
else if (!frame.size)
|
|
542
|
+
setTimeout(() => {
|
|
543
|
+
flush(this);
|
|
544
|
+
const keys = this.latest = Array.from(frame);
|
|
545
|
+
setTimeout(() => this.latest = undefined, 0);
|
|
546
|
+
frame.clear();
|
|
547
|
+
for (const notify of waiting)
|
|
548
|
+
try {
|
|
549
|
+
waiting.delete(notify);
|
|
550
|
+
notify(keys);
|
|
551
|
+
}
|
|
552
|
+
catch (err) {
|
|
553
|
+
console.error(err);
|
|
554
|
+
}
|
|
555
|
+
}, 0);
|
|
556
|
+
frame.add(key);
|
|
557
|
+
for (const callback of followers) {
|
|
558
|
+
const event = callback(key, this);
|
|
559
|
+
if (typeof event == "function")
|
|
560
|
+
waiting.add(event);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
clear() {
|
|
564
|
+
const listeners = [...this.followers];
|
|
565
|
+
this.followers.clear();
|
|
566
|
+
listeners.forEach(x => x(null, this));
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function controller(from) {
|
|
570
|
+
if ("is" in from)
|
|
571
|
+
from = from.is;
|
|
572
|
+
return REGISTER.get(from);
|
|
573
|
+
}
|
|
574
|
+
function control(subject, cb) {
|
|
575
|
+
const control = controller(subject) || new Control(subject);
|
|
576
|
+
if (!control.state) {
|
|
577
|
+
const { waiting } = control;
|
|
578
|
+
if (cb) {
|
|
579
|
+
let callback;
|
|
580
|
+
waiting.add(() => {
|
|
581
|
+
callback = cb(control);
|
|
582
|
+
});
|
|
583
|
+
return () => {
|
|
584
|
+
if (callback)
|
|
585
|
+
callback();
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
control.state = new Map();
|
|
589
|
+
for (const key in subject)
|
|
590
|
+
control.watch(key);
|
|
591
|
+
control.waiting = new Set();
|
|
592
|
+
for (const cb of waiting)
|
|
593
|
+
cb([]);
|
|
594
|
+
}
|
|
595
|
+
return cb ? cb(control) : control;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const Parent = new WeakMap();
|
|
599
|
+
const Oops$a = issues({
|
|
600
|
+
BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`
|
|
601
|
+
});
|
|
602
|
+
function getRecursive(key, from) {
|
|
603
|
+
const context = new WeakMap();
|
|
604
|
+
const { state } = from;
|
|
605
|
+
return (local) => {
|
|
606
|
+
if (!local)
|
|
607
|
+
return state.get(key);
|
|
608
|
+
if (!context.has(local)) {
|
|
609
|
+
let reset;
|
|
610
|
+
const init = () => {
|
|
611
|
+
if (reset)
|
|
612
|
+
reset();
|
|
613
|
+
const value = state.get(key);
|
|
614
|
+
if (value && controller(value)) {
|
|
615
|
+
const child = control(value).subscribe(local.onUpdate);
|
|
616
|
+
if (local.active)
|
|
617
|
+
child.commit();
|
|
618
|
+
local.dependant.add(child);
|
|
619
|
+
context.set(local, child.proxy);
|
|
620
|
+
reset = () => {
|
|
621
|
+
child.release();
|
|
622
|
+
local.dependant.delete(child);
|
|
623
|
+
context.set(local, undefined);
|
|
624
|
+
reset = undefined;
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
return true;
|
|
628
|
+
};
|
|
629
|
+
local.add(key, init);
|
|
630
|
+
init();
|
|
631
|
+
}
|
|
632
|
+
return context.get(local);
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function setRecursive(controller, key, initial) {
|
|
636
|
+
const { state, subject } = controller;
|
|
637
|
+
const Type = initial.constructor;
|
|
638
|
+
let get;
|
|
639
|
+
const onUpdate = (next) => {
|
|
640
|
+
state.set(key, next);
|
|
641
|
+
if (!(next instanceof Type))
|
|
642
|
+
throw Oops$a.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
643
|
+
get = getRecursive(key, controller);
|
|
644
|
+
Parent.set(next, subject);
|
|
645
|
+
control(next);
|
|
646
|
+
return true;
|
|
647
|
+
};
|
|
648
|
+
onUpdate(initial);
|
|
649
|
+
defineProperty(subject, key, {
|
|
650
|
+
set: controller.ref(key, onUpdate),
|
|
651
|
+
get() {
|
|
652
|
+
const local = subscriber(this);
|
|
653
|
+
if (local)
|
|
654
|
+
local.add(key);
|
|
655
|
+
return get(local);
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Run instruction as controller sets itself up.
|
|
662
|
+
* This will specialize the behavior of a given property.
|
|
663
|
+
*/
|
|
664
|
+
function add(instruction, label) {
|
|
665
|
+
const name = label || instruction.name || "pending";
|
|
666
|
+
const placeholder = Symbol(`${name} instruction`);
|
|
667
|
+
function setup(key) {
|
|
668
|
+
const { subject, state } = this;
|
|
669
|
+
let output = instruction.call(this, key, this);
|
|
670
|
+
if (typeof output == "function")
|
|
671
|
+
output = { get: output };
|
|
672
|
+
if (typeof output != "object")
|
|
673
|
+
return;
|
|
674
|
+
if ("explicit" in output && output.explicit) {
|
|
675
|
+
defineProperty(subject, key, output);
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
let { get: onGet, set: onSet, suspend: shouldSuspend } = output;
|
|
679
|
+
if ("value" in output)
|
|
680
|
+
state.set(key, output.value);
|
|
681
|
+
if ("recursive" in output && output.recursive)
|
|
682
|
+
onGet = getRecursive(key, this);
|
|
683
|
+
if ("destroy" in output) {
|
|
684
|
+
const { destroy } = output;
|
|
685
|
+
if (destroy)
|
|
686
|
+
this.addListener((key) => {
|
|
687
|
+
if (key == null)
|
|
688
|
+
destroy();
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
const control = this;
|
|
692
|
+
defineProperty(subject, key, {
|
|
693
|
+
enumerable: output.enumerable,
|
|
694
|
+
set: onSet === false
|
|
695
|
+
? undefined
|
|
696
|
+
: this.ref(key, onSet),
|
|
697
|
+
get() {
|
|
698
|
+
if (!state.has(key) && shouldSuspend)
|
|
699
|
+
throw suspend(control, key);
|
|
700
|
+
const local = subscriber(this);
|
|
701
|
+
if (local)
|
|
702
|
+
local.add(key);
|
|
703
|
+
return onGet
|
|
704
|
+
? onGet(local)
|
|
705
|
+
: state.get(key);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
PENDING.set(placeholder, setup);
|
|
710
|
+
return placeholder;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/*! *****************************************************************************
|
|
714
|
+
Copyright (c) Microsoft Corporation.
|
|
715
|
+
|
|
716
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
717
|
+
purpose with or without fee is hereby granted.
|
|
718
|
+
|
|
719
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
720
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
721
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
722
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
723
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
724
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
725
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
726
|
+
***************************************************************************** */
|
|
727
|
+
|
|
728
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
729
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
730
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
731
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
732
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
733
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
734
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
const Oops$9 = issues({
|
|
739
|
+
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
740
|
+
});
|
|
741
|
+
function run(task) {
|
|
742
|
+
return add(function run(key) {
|
|
743
|
+
let pending = false;
|
|
744
|
+
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
745
|
+
if (pending)
|
|
746
|
+
return Promise.reject(Oops$9.DuplicatePending(key));
|
|
747
|
+
pending = true;
|
|
748
|
+
this.update(key);
|
|
749
|
+
try {
|
|
750
|
+
return yield mayRetry(() => (task.apply(this.subject, args)));
|
|
751
|
+
}
|
|
752
|
+
finally {
|
|
753
|
+
pending = false;
|
|
754
|
+
this.update(key);
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
this.state.set(key, undefined);
|
|
758
|
+
defineProperty(invoke, "active", {
|
|
759
|
+
get: () => pending
|
|
760
|
+
});
|
|
761
|
+
return {
|
|
762
|
+
value: invoke,
|
|
763
|
+
set: false
|
|
764
|
+
};
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
const Oops$8 = issues({
|
|
769
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
770
|
+
});
|
|
771
|
+
function factoryMode(self, value, key, required) {
|
|
772
|
+
const { subject, state } = self;
|
|
773
|
+
let pending;
|
|
774
|
+
let error;
|
|
775
|
+
if (value instanceof Promise) {
|
|
776
|
+
state.set(key, undefined);
|
|
777
|
+
pending = value
|
|
778
|
+
.catch(err => error = err)
|
|
779
|
+
.then(val => {
|
|
780
|
+
state.set(key, val);
|
|
781
|
+
return val;
|
|
782
|
+
})
|
|
783
|
+
.finally(() => {
|
|
784
|
+
pending = undefined;
|
|
785
|
+
self.update(key);
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
else
|
|
789
|
+
state.set(key, value);
|
|
790
|
+
const suspend = () => {
|
|
791
|
+
if (required === false)
|
|
792
|
+
return undefined;
|
|
793
|
+
const issue = Oops$8.NotReady(subject, key);
|
|
794
|
+
assign(pending, {
|
|
795
|
+
message: issue.message,
|
|
796
|
+
stack: issue.stack
|
|
797
|
+
});
|
|
798
|
+
throw pending;
|
|
799
|
+
};
|
|
800
|
+
return () => {
|
|
801
|
+
if (error)
|
|
802
|
+
throw error;
|
|
803
|
+
if (pending)
|
|
804
|
+
return suspend();
|
|
805
|
+
if (state.has(key))
|
|
806
|
+
return state.get(key);
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const Oops$7 = issues({
|
|
811
|
+
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
812
|
+
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
813
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
814
|
+
});
|
|
815
|
+
function get(arg0, arg1, arg2) {
|
|
816
|
+
return add(function get(key) {
|
|
817
|
+
const { subject } = this;
|
|
818
|
+
const computeRequired = arg1 === true || arg2 === true;
|
|
819
|
+
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
820
|
+
let getter;
|
|
821
|
+
// Easy mistake, using a peer, will always be unresolved.
|
|
822
|
+
if (typeof arg0 == "symbol")
|
|
823
|
+
throw Oops$7.PeerNotAllowed(subject, key);
|
|
824
|
+
// if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
825
|
+
// throw Oops.BadSource(subject, key, arg0);
|
|
826
|
+
this.state.set(key, undefined);
|
|
827
|
+
const init = () => {
|
|
828
|
+
let source = this;
|
|
829
|
+
let setter;
|
|
830
|
+
if (typeof arg0 == "function") {
|
|
831
|
+
let result = mayRetry(arg0.bind(subject, key, subject));
|
|
832
|
+
if (typeof result == "function")
|
|
833
|
+
setter = result;
|
|
834
|
+
else {
|
|
835
|
+
getter = factoryMode(this, result, key, factoryRequired);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
else if (arg0 instanceof Promise) {
|
|
840
|
+
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
else if (typeof arg1 == "function") {
|
|
844
|
+
// replace source controller in-case it is different
|
|
845
|
+
source = control(arg0);
|
|
846
|
+
setter = arg1;
|
|
847
|
+
}
|
|
848
|
+
else
|
|
849
|
+
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
850
|
+
getter = computeMode(this, source, setter, key, computeRequired);
|
|
851
|
+
};
|
|
852
|
+
if (typeof arg0 == "function" && computeRequired)
|
|
853
|
+
try {
|
|
854
|
+
init();
|
|
855
|
+
}
|
|
856
|
+
catch (err) {
|
|
857
|
+
Oops$7.ComputeFailed(subject, key).warn();
|
|
858
|
+
throw err;
|
|
859
|
+
}
|
|
860
|
+
return () => {
|
|
861
|
+
if (!getter)
|
|
862
|
+
init();
|
|
863
|
+
return getter();
|
|
864
|
+
};
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
function ref(arg, mapper) {
|
|
869
|
+
return add(function ref(key) {
|
|
870
|
+
let value = {};
|
|
871
|
+
this.state.set(key, undefined);
|
|
872
|
+
if (typeof arg != "object")
|
|
873
|
+
value = createRef(this, key, arg);
|
|
874
|
+
else
|
|
875
|
+
control(arg).state.forEach((_val, key) => {
|
|
876
|
+
defineProperty(value, key, mapper ? {
|
|
877
|
+
configurable: true,
|
|
878
|
+
get() {
|
|
879
|
+
const out = mapper(key);
|
|
880
|
+
defineProperty(value, key, { value: out });
|
|
881
|
+
return out;
|
|
882
|
+
}
|
|
883
|
+
} : {
|
|
884
|
+
value: createRef(this, key)
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
return { value, explicit: true };
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
function createRef(src, key, cb) {
|
|
891
|
+
const refObjectFunction = src.ref(key, cb && createValueEffect(cb));
|
|
892
|
+
defineProperty(refObjectFunction, "current", {
|
|
893
|
+
set: refObjectFunction,
|
|
894
|
+
get: () => src.state.get(key)
|
|
895
|
+
});
|
|
896
|
+
return refObjectFunction;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
function set(value, argument) {
|
|
900
|
+
if (!(1 in arguments)) {
|
|
901
|
+
argument = value;
|
|
902
|
+
value = undefined;
|
|
903
|
+
}
|
|
904
|
+
return add(function set(key) {
|
|
905
|
+
if (value !== undefined)
|
|
906
|
+
this.state.set(key, value);
|
|
907
|
+
return {
|
|
908
|
+
suspend: true,
|
|
909
|
+
set: typeof argument == "function"
|
|
910
|
+
? createValueEffect(argument)
|
|
911
|
+
: undefined
|
|
912
|
+
};
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const ANY = Symbol("any");
|
|
917
|
+
function keyed(control, property, initial) {
|
|
918
|
+
const init = createProxy(emit, watch);
|
|
919
|
+
const frozen = new Set();
|
|
920
|
+
const context = new Map();
|
|
921
|
+
const users = new Map();
|
|
922
|
+
const watched = new WeakMap();
|
|
923
|
+
const update = new Set();
|
|
924
|
+
let managed = init(initial);
|
|
925
|
+
function watch(on, key) {
|
|
926
|
+
const include = watched.get(on);
|
|
927
|
+
if (include)
|
|
928
|
+
include.add(key);
|
|
929
|
+
}
|
|
930
|
+
function emit(key) {
|
|
931
|
+
control.update(property);
|
|
932
|
+
control.waiting.add(() => frozen.clear());
|
|
933
|
+
update.forEach(notify => notify(key));
|
|
934
|
+
}
|
|
935
|
+
function subscribe(local) {
|
|
936
|
+
const proxy = create(managed);
|
|
937
|
+
let watch = users.get(local);
|
|
938
|
+
if (!watch) {
|
|
939
|
+
const using = watch = new Set();
|
|
940
|
+
users.set(local, using);
|
|
941
|
+
function onEvent(key) {
|
|
942
|
+
if (frozen.has(local))
|
|
943
|
+
return;
|
|
944
|
+
if (key === ANY || using.has(key) || using.has(ANY)) {
|
|
945
|
+
const refresh = local.onUpdate(property, control);
|
|
946
|
+
if (refresh) {
|
|
947
|
+
frozen.add(local);
|
|
948
|
+
refresh();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
local.add(property, false);
|
|
953
|
+
local.dependant.add({
|
|
954
|
+
commit() {
|
|
955
|
+
if (using.size === 0)
|
|
956
|
+
using.add(ANY);
|
|
957
|
+
update.add(onEvent);
|
|
958
|
+
},
|
|
959
|
+
release() {
|
|
960
|
+
update.delete(onEvent);
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
watched.set(proxy, watch);
|
|
965
|
+
context.set(local, proxy);
|
|
966
|
+
return proxy;
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
value: initial,
|
|
970
|
+
get(local) {
|
|
971
|
+
return local ?
|
|
972
|
+
context.get(local) || subscribe(local) :
|
|
973
|
+
managed;
|
|
974
|
+
},
|
|
975
|
+
set(next) {
|
|
976
|
+
control.state.set(property, next);
|
|
977
|
+
managed = init(next);
|
|
978
|
+
context.clear();
|
|
979
|
+
emit(ANY);
|
|
980
|
+
},
|
|
981
|
+
destroy() {
|
|
982
|
+
update.clear();
|
|
983
|
+
context.clear();
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
function createProxy(emit, watch) {
|
|
988
|
+
return (from) => {
|
|
989
|
+
const proxy = create(from);
|
|
990
|
+
assign(proxy, {
|
|
991
|
+
from,
|
|
992
|
+
delete(key) {
|
|
993
|
+
// TODO: this commit's fix needs tests.
|
|
994
|
+
// Was not cause by coverage.
|
|
995
|
+
const out = from.delete(key);
|
|
996
|
+
emit(key);
|
|
997
|
+
return out;
|
|
998
|
+
},
|
|
999
|
+
clear() {
|
|
1000
|
+
from.clear();
|
|
1001
|
+
emit(ANY);
|
|
1002
|
+
},
|
|
1003
|
+
has(key) {
|
|
1004
|
+
watch(this, key);
|
|
1005
|
+
return from.has(key);
|
|
1006
|
+
},
|
|
1007
|
+
keys() {
|
|
1008
|
+
watch(this, ANY);
|
|
1009
|
+
return from.keys();
|
|
1010
|
+
},
|
|
1011
|
+
values() {
|
|
1012
|
+
watch(this, ANY);
|
|
1013
|
+
return from.values();
|
|
1014
|
+
},
|
|
1015
|
+
entries() {
|
|
1016
|
+
watch(this, ANY);
|
|
1017
|
+
return from.entries();
|
|
1018
|
+
},
|
|
1019
|
+
forEach(callbackfn, thisArg) {
|
|
1020
|
+
const acc = [];
|
|
1021
|
+
from.forEach((a, b, c) => {
|
|
1022
|
+
const result = callbackfn.call(thisArg, a, b, c);
|
|
1023
|
+
if (result !== undefined)
|
|
1024
|
+
acc.push(result);
|
|
1025
|
+
});
|
|
1026
|
+
watch(this, ANY);
|
|
1027
|
+
return acc;
|
|
1028
|
+
},
|
|
1029
|
+
[Symbol.iterator]() {
|
|
1030
|
+
watch(this, ANY);
|
|
1031
|
+
return from[Symbol.iterator]();
|
|
1032
|
+
},
|
|
1033
|
+
}, from instanceof Set
|
|
1034
|
+
? {
|
|
1035
|
+
add(key) {
|
|
1036
|
+
from.add(key);
|
|
1037
|
+
emit(key);
|
|
1038
|
+
return this;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
: {
|
|
1042
|
+
get(key) {
|
|
1043
|
+
watch(this, ANY);
|
|
1044
|
+
return from.get(key);
|
|
1045
|
+
},
|
|
1046
|
+
set(key, value) {
|
|
1047
|
+
from.set(key, value);
|
|
1048
|
+
emit(key);
|
|
1049
|
+
return this;
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
defineProperty(proxy, "size", {
|
|
1053
|
+
get() {
|
|
1054
|
+
watch(this, ANY);
|
|
1055
|
+
return from.size;
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
return proxy;
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const Oops$6 = issues({
|
|
1063
|
+
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1064
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1065
|
+
});
|
|
1066
|
+
function use$1(input, argument) {
|
|
1067
|
+
return add(function use(key) {
|
|
1068
|
+
const { state, subject } = this;
|
|
1069
|
+
const required = argument !== false;
|
|
1070
|
+
let pending;
|
|
1071
|
+
let error;
|
|
1072
|
+
let get = (_local) => state.get(key);
|
|
1073
|
+
if (typeof input === "function") {
|
|
1074
|
+
if ("prototype" in input && input === input.prototype.constructor)
|
|
1075
|
+
input = new input();
|
|
1076
|
+
}
|
|
1077
|
+
else if (input && typeof input !== "object")
|
|
1078
|
+
throw Oops$6.BadArgument(typeof input);
|
|
1079
|
+
if (input instanceof Map || input instanceof Set)
|
|
1080
|
+
return keyed(this, key, input);
|
|
1081
|
+
const onUpdate = (next) => {
|
|
1082
|
+
state.set(key, next);
|
|
1083
|
+
if (next) {
|
|
1084
|
+
get = getRecursive(key, this);
|
|
1085
|
+
Parent.set(next, subject);
|
|
1086
|
+
control(next);
|
|
1087
|
+
}
|
|
1088
|
+
if (typeof argument == "function")
|
|
1089
|
+
argument(next);
|
|
1090
|
+
return true;
|
|
1091
|
+
};
|
|
1092
|
+
const suspend = () => {
|
|
1093
|
+
if (required === false)
|
|
1094
|
+
return;
|
|
1095
|
+
const issue = Oops$6.NotReady(subject, key);
|
|
1096
|
+
assign(pending, {
|
|
1097
|
+
message: issue.message,
|
|
1098
|
+
stack: issue.stack
|
|
1099
|
+
});
|
|
1100
|
+
throw pending;
|
|
1101
|
+
};
|
|
1102
|
+
const initialize = () => {
|
|
1103
|
+
const output = typeof input == "function" ?
|
|
1104
|
+
mayRetry(() => input.call(subject, subject)) :
|
|
1105
|
+
input;
|
|
1106
|
+
if (output instanceof Promise) {
|
|
1107
|
+
pending = output
|
|
1108
|
+
.catch(err => error = err)
|
|
1109
|
+
.then(val => {
|
|
1110
|
+
onUpdate(val);
|
|
1111
|
+
return val;
|
|
1112
|
+
})
|
|
1113
|
+
.finally(() => {
|
|
1114
|
+
pending = undefined;
|
|
1115
|
+
this.update(key);
|
|
1116
|
+
});
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
onUpdate(output);
|
|
1120
|
+
};
|
|
1121
|
+
if (input !== undefined && required)
|
|
1122
|
+
initialize();
|
|
1123
|
+
return {
|
|
1124
|
+
set: onUpdate,
|
|
1125
|
+
get(local) {
|
|
1126
|
+
if (pending)
|
|
1127
|
+
return suspend();
|
|
1128
|
+
if (error)
|
|
1129
|
+
throw error;
|
|
1130
|
+
if (!state.has(key))
|
|
1131
|
+
initialize();
|
|
1132
|
+
if (pending)
|
|
1133
|
+
return suspend();
|
|
1134
|
+
return get(local);
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
const Oops$5 = issues({
|
|
1141
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1142
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1143
|
+
});
|
|
1144
|
+
function has(Type, required) {
|
|
1145
|
+
return add(function parent() {
|
|
1146
|
+
const child = this.subject;
|
|
1147
|
+
const value = Parent.get(child);
|
|
1148
|
+
const expected = Type.name;
|
|
1149
|
+
if (!value) {
|
|
1150
|
+
if (required !== false)
|
|
1151
|
+
throw Oops$5.Required(expected, child);
|
|
1152
|
+
}
|
|
1153
|
+
else if (!(value instanceof Type))
|
|
1154
|
+
throw Oops$5.Unexpected(expected, child, value);
|
|
1155
|
+
return { value };
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
const Oops$4 = issues({
|
|
1160
|
+
NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
|
|
1161
|
+
});
|
|
1162
|
+
class Lookup {
|
|
1163
|
+
constructor() {
|
|
1164
|
+
this.table = new Map();
|
|
1165
|
+
}
|
|
1166
|
+
key(T) {
|
|
1167
|
+
let key = this.table.get(T);
|
|
1168
|
+
if (!key) {
|
|
1169
|
+
key = Symbol(T.name);
|
|
1170
|
+
this.table.set(T, key);
|
|
1171
|
+
}
|
|
1172
|
+
return key;
|
|
1173
|
+
}
|
|
1174
|
+
get(Type) {
|
|
1175
|
+
return this[this.key(Type)];
|
|
1176
|
+
}
|
|
1177
|
+
has(key, input, callback) {
|
|
1178
|
+
if (MVC.isTypeof(input) && input.global)
|
|
1179
|
+
return input.new();
|
|
1180
|
+
if (this.register.get(key) === input)
|
|
1181
|
+
return typeof input == "object"
|
|
1182
|
+
? input
|
|
1183
|
+
: this.get(input);
|
|
1184
|
+
const instance = this.add(input);
|
|
1185
|
+
this.register.set(key, input);
|
|
1186
|
+
if (callback)
|
|
1187
|
+
callback(instance);
|
|
1188
|
+
return instance;
|
|
1189
|
+
}
|
|
1190
|
+
add(input) {
|
|
1191
|
+
let writable = true;
|
|
1192
|
+
let T;
|
|
1193
|
+
let I;
|
|
1194
|
+
if (typeof input == "function") {
|
|
1195
|
+
T = input;
|
|
1196
|
+
I = new input();
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
I = input;
|
|
1200
|
+
T = I.constructor;
|
|
1201
|
+
writable = false;
|
|
1202
|
+
}
|
|
1203
|
+
do {
|
|
1204
|
+
const key = this.key(T);
|
|
1205
|
+
defineProperty(this, key, {
|
|
1206
|
+
configurable: true,
|
|
1207
|
+
value: this.hasOwnProperty(key) ? null : I,
|
|
1208
|
+
writable
|
|
1209
|
+
});
|
|
1210
|
+
T = getPrototypeOf(T);
|
|
1211
|
+
} while (T !== Model);
|
|
1212
|
+
return I;
|
|
1213
|
+
}
|
|
1214
|
+
push() {
|
|
1215
|
+
const next = create(this);
|
|
1216
|
+
next.register = new Map();
|
|
1217
|
+
return next;
|
|
1218
|
+
}
|
|
1219
|
+
pop() {
|
|
1220
|
+
const items = new Set();
|
|
1221
|
+
for (const key of getOwnPropertySymbols(this)) {
|
|
1222
|
+
const entry = getOwnPropertyDescriptor(this, key);
|
|
1223
|
+
if (entry.writable && entry.value)
|
|
1224
|
+
items.add(entry.value);
|
|
1225
|
+
}
|
|
1226
|
+
for (const model of items)
|
|
1227
|
+
model.end();
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
const LookupContext = React.createContext(new Lookup());
|
|
1231
|
+
const useLookup = () => React.useContext(LookupContext);
|
|
1232
|
+
function useContext(Type, required) {
|
|
1233
|
+
const instance = useLookup().get(Type);
|
|
1234
|
+
if (!instance && required !== false)
|
|
1235
|
+
throw Oops$4.NotFound(Type.name);
|
|
1236
|
+
return instance;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
const Oops$3 = issues({
|
|
1240
|
+
NotAllowed: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
1241
|
+
AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
|
|
1242
|
+
});
|
|
1243
|
+
const Pending = new WeakMap();
|
|
1244
|
+
const Applied = new WeakMap();
|
|
1245
|
+
function tap(type, argument) {
|
|
1246
|
+
return add(function tap(key) {
|
|
1247
|
+
if (MVC.isTypeof(type) && type.global)
|
|
1248
|
+
return {
|
|
1249
|
+
recursive: true,
|
|
1250
|
+
value: type.get()
|
|
1251
|
+
};
|
|
1252
|
+
const { subject } = this;
|
|
1253
|
+
if (subject.constructor.global)
|
|
1254
|
+
throw Oops$3.NotAllowed(subject, type.name);
|
|
1255
|
+
getPending(subject).push(context => {
|
|
1256
|
+
let instance = context.get(type);
|
|
1257
|
+
if (typeof argument == "function") {
|
|
1258
|
+
if (argument(instance) === false)
|
|
1259
|
+
instance = undefined;
|
|
1260
|
+
}
|
|
1261
|
+
else if (!instance && argument)
|
|
1262
|
+
throw Oops$3.AmbientRequired(type.name, subject, key);
|
|
1263
|
+
this.state.set(key, instance);
|
|
1264
|
+
this.update(key);
|
|
1265
|
+
});
|
|
1266
|
+
return {
|
|
1267
|
+
recursive: true,
|
|
1268
|
+
suspend: true
|
|
1269
|
+
};
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
function usePeerContext(subject) {
|
|
1273
|
+
if (Applied.has(subject)) {
|
|
1274
|
+
if (Applied.get(subject))
|
|
1275
|
+
useLookup();
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
const pending = Pending.get(subject);
|
|
1279
|
+
if (pending) {
|
|
1280
|
+
const local = useLookup();
|
|
1281
|
+
for (const init of pending)
|
|
1282
|
+
init(local);
|
|
1283
|
+
Pending.delete(subject);
|
|
1284
|
+
}
|
|
1285
|
+
Applied.set(subject, !!pending);
|
|
1286
|
+
}
|
|
1287
|
+
function getPending(subject) {
|
|
1288
|
+
let pending = Pending.get(subject);
|
|
1289
|
+
if (!pending)
|
|
1290
|
+
Pending.set(subject, pending = []);
|
|
1291
|
+
return pending;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
function useNew(source, arg1, arg2) {
|
|
1295
|
+
const instance = React.useMemo(() => {
|
|
1296
|
+
const callback = arg2 || arg1;
|
|
1297
|
+
const instance = Model.isTypeof(source)
|
|
1298
|
+
? new source()
|
|
1299
|
+
: source();
|
|
1300
|
+
control(instance);
|
|
1301
|
+
if (typeof callback == "function")
|
|
1302
|
+
callback(instance);
|
|
1303
|
+
return instance;
|
|
1304
|
+
}, []);
|
|
1305
|
+
usePeerContext(instance);
|
|
1306
|
+
if (Array.isArray(arg1)) {
|
|
1307
|
+
const update = useState(0)[1];
|
|
1308
|
+
React.useLayoutEffect(() => {
|
|
1309
|
+
if (arg1.length && instance instanceof Model)
|
|
1310
|
+
instance.on(arg1, () => update(x => x + 1));
|
|
1311
|
+
return () => {
|
|
1312
|
+
if (Model.isTypeof(source))
|
|
1313
|
+
instance.end();
|
|
1314
|
+
};
|
|
1315
|
+
}, []);
|
|
1316
|
+
return instance;
|
|
1317
|
+
}
|
|
1318
|
+
const state = React.useState(0);
|
|
1319
|
+
const local = React.useMemo(() => {
|
|
1320
|
+
const refresh = state[1].bind(null, x => x + 1);
|
|
1321
|
+
return control(instance).subscribe(() => refresh);
|
|
1322
|
+
}, []);
|
|
1323
|
+
if (typeof arg1 == "object") {
|
|
1324
|
+
const { waiting, subject } = local.parent;
|
|
1325
|
+
let keys = arg2;
|
|
1326
|
+
local.active = false;
|
|
1327
|
+
if (!keys)
|
|
1328
|
+
keys = getOwnPropertyNames(subject);
|
|
1329
|
+
for (const key of keys)
|
|
1330
|
+
if (key in arg1)
|
|
1331
|
+
subject[key] = arg1[key];
|
|
1332
|
+
waiting.add(() => local.active = true);
|
|
1333
|
+
}
|
|
1334
|
+
React.useLayoutEffect(() => {
|
|
1335
|
+
local.commit();
|
|
1336
|
+
return () => {
|
|
1337
|
+
local.release();
|
|
1338
|
+
if (Model.isTypeof(source))
|
|
1339
|
+
instance.end();
|
|
1340
|
+
};
|
|
1341
|
+
}, []);
|
|
1342
|
+
return local.proxy;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
function use(init, deps) {
|
|
1346
|
+
const state = React.useState(0);
|
|
1347
|
+
return React.useMemo(() => {
|
|
1348
|
+
return init(state[1].bind(null, x => x + 1));
|
|
1349
|
+
}, deps);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
function useCompute(source, compute, suspend) {
|
|
1353
|
+
const deps = [uid(source)];
|
|
1354
|
+
const local = use(refresh => {
|
|
1355
|
+
const sub = control(source).subscribe(() => update);
|
|
1356
|
+
const spy = sub.proxy;
|
|
1357
|
+
let make = () => compute.call(spy, spy, forceUpdate);
|
|
1358
|
+
function forceUpdate(passthru) {
|
|
1359
|
+
if (make)
|
|
1360
|
+
reassign(make());
|
|
1361
|
+
else
|
|
1362
|
+
refresh();
|
|
1363
|
+
if (passthru)
|
|
1364
|
+
return passthru.finally(refresh);
|
|
1365
|
+
}
|
|
1366
|
+
function reassign(next) {
|
|
1367
|
+
value = next;
|
|
1368
|
+
if (retry) {
|
|
1369
|
+
retry();
|
|
1370
|
+
retry = undefined;
|
|
1371
|
+
}
|
|
1372
|
+
else
|
|
1373
|
+
refresh();
|
|
1374
|
+
}
|
|
1375
|
+
let retry;
|
|
1376
|
+
let update;
|
|
1377
|
+
let value = make();
|
|
1378
|
+
if (value === null) {
|
|
1379
|
+
sub.watch.clear();
|
|
1380
|
+
make = undefined;
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
if (typeof value == "function") {
|
|
1384
|
+
const get = value;
|
|
1385
|
+
sub.watch.clear();
|
|
1386
|
+
compute = () => get();
|
|
1387
|
+
value = get();
|
|
1388
|
+
}
|
|
1389
|
+
if (value instanceof Promise) {
|
|
1390
|
+
value.then(reassign);
|
|
1391
|
+
value = undefined;
|
|
1392
|
+
}
|
|
1393
|
+
else {
|
|
1394
|
+
sub.commit();
|
|
1395
|
+
update = () => {
|
|
1396
|
+
const next = make();
|
|
1397
|
+
if (value != next)
|
|
1398
|
+
reassign(next);
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
defineProperty(sub, "proxy", {
|
|
1402
|
+
get() {
|
|
1403
|
+
if (value !== undefined)
|
|
1404
|
+
return value;
|
|
1405
|
+
if (suspend)
|
|
1406
|
+
throw new Promise(res => retry = res);
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
return sub;
|
|
1411
|
+
}, deps);
|
|
1412
|
+
if (!local)
|
|
1413
|
+
return null;
|
|
1414
|
+
React.useLayoutEffect(() => local.release, deps);
|
|
1415
|
+
return local.proxy;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
function useTap(source, arg1, arg2) {
|
|
1419
|
+
const instance = typeof source == "object"
|
|
1420
|
+
? source
|
|
1421
|
+
: "get" in source
|
|
1422
|
+
? source.get()
|
|
1423
|
+
: useContext(source);
|
|
1424
|
+
return typeof arg1 == "function"
|
|
1425
|
+
? useCompute(instance, arg1, arg2)
|
|
1426
|
+
: useSubscribe(instance, arg1, arg2);
|
|
1427
|
+
}
|
|
1428
|
+
function useSubscribe(source, path, expect) {
|
|
1429
|
+
const deps = [uid(source)];
|
|
1430
|
+
const local = use(refresh => (control(source).subscribe(() => refresh)), deps);
|
|
1431
|
+
React.useLayoutEffect(() => local.commit(), deps);
|
|
1432
|
+
if (path === undefined)
|
|
1433
|
+
return local.proxy;
|
|
1434
|
+
const value = local.proxy[path];
|
|
1435
|
+
if (value === undefined && expect)
|
|
1436
|
+
throw suspend(local.parent, path);
|
|
1437
|
+
return value;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
const Global$1 = new WeakMap();
|
|
1441
|
+
const Oops$2 = issues({
|
|
1442
|
+
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.`,
|
|
1443
|
+
AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
|
|
1444
|
+
});
|
|
1445
|
+
class MVC extends Model {
|
|
1446
|
+
end(force) {
|
|
1447
|
+
const type = this.constructor;
|
|
1448
|
+
if (type.keepAlive && !force)
|
|
1449
|
+
return false;
|
|
1450
|
+
super.end();
|
|
1451
|
+
Global$1.delete(type);
|
|
1452
|
+
return true;
|
|
1453
|
+
}
|
|
1454
|
+
static new(...args) {
|
|
1455
|
+
if (Global$1.has(this))
|
|
1456
|
+
if (this.keepAlive)
|
|
1457
|
+
return Global$1.get(this);
|
|
1458
|
+
else
|
|
1459
|
+
throw Oops$2.AlreadyExists(this.name);
|
|
1460
|
+
const instance = super.new(...args);
|
|
1461
|
+
if (this.global)
|
|
1462
|
+
Global$1.set(this, instance);
|
|
1463
|
+
return instance;
|
|
1464
|
+
}
|
|
1465
|
+
static get(arg1, arg2) {
|
|
1466
|
+
let instance;
|
|
1467
|
+
const required = arg1 === undefined || arg1 === true;
|
|
1468
|
+
if (this.global) {
|
|
1469
|
+
instance = Global$1.get(this);
|
|
1470
|
+
if (!instance && required)
|
|
1471
|
+
throw Oops$2.DoesNotExist(this.name);
|
|
1472
|
+
}
|
|
1473
|
+
else
|
|
1474
|
+
instance = useContext(this, required);
|
|
1475
|
+
function callback(effect) {
|
|
1476
|
+
try {
|
|
1477
|
+
React.useLayoutEffect(() => effect(instance), []);
|
|
1478
|
+
}
|
|
1479
|
+
catch (err) {
|
|
1480
|
+
if (instance)
|
|
1481
|
+
instance.on(effect, []);
|
|
1482
|
+
else
|
|
1483
|
+
effect(undefined);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
if (typeof arg1 === "string")
|
|
1487
|
+
return instance[arg1];
|
|
1488
|
+
if (typeof arg1 === "function" && instance)
|
|
1489
|
+
callback(arg1);
|
|
1490
|
+
else if (arg2)
|
|
1491
|
+
callback(arg2);
|
|
1492
|
+
return instance;
|
|
1493
|
+
}
|
|
1494
|
+
static tap(arg1, arg2) {
|
|
1495
|
+
const instance = this.get();
|
|
1496
|
+
return typeof arg1 == "function"
|
|
1497
|
+
? useCompute(instance, arg1, arg2)
|
|
1498
|
+
: useSubscribe(instance, arg1, arg2);
|
|
1499
|
+
}
|
|
1500
|
+
static use(a, b) {
|
|
1501
|
+
return useNew(this, a, b);
|
|
1502
|
+
}
|
|
1503
|
+
static meta(arg1, arg2) {
|
|
1504
|
+
return typeof arg1 == "function"
|
|
1505
|
+
? useCompute(this, arg1, arg2)
|
|
1506
|
+
: useSubscribe(this, arg1, arg2);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
const Oops$1 = issues({
|
|
1511
|
+
BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
|
|
1512
|
+
});
|
|
1513
|
+
function Consumer(props) {
|
|
1514
|
+
const { get, has, children, for: type } = props;
|
|
1515
|
+
if (typeof children == "function")
|
|
1516
|
+
return children(useTap(type));
|
|
1517
|
+
const callback = has || get;
|
|
1518
|
+
if (typeof callback == "function")
|
|
1519
|
+
callback(useContext(type, !!has));
|
|
1520
|
+
else
|
|
1521
|
+
throw Oops$1.BadProps();
|
|
1522
|
+
return null;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
const Oops = issues({
|
|
1526
|
+
NoType: () => "Provider 'for' prop must be Model, typeof Model or a collection of them."
|
|
1527
|
+
});
|
|
1528
|
+
function Provider(props) {
|
|
1529
|
+
const context = useNewContext(props.for, props.and);
|
|
1530
|
+
return (React.createElement(LookupContext.Provider, { value: context }, props.fallback === false
|
|
1531
|
+
? props.children
|
|
1532
|
+
: (React.createElement(Suspense, { fallback: props.fallback || null }, props.children))));
|
|
1533
|
+
}
|
|
1534
|
+
function useNewContext(include, assign) {
|
|
1535
|
+
const init = new Set();
|
|
1536
|
+
const ambient = useLookup();
|
|
1537
|
+
const context = React.useMemo(() => {
|
|
1538
|
+
if (!include)
|
|
1539
|
+
throw Oops.NoType();
|
|
1540
|
+
return ambient.push();
|
|
1541
|
+
}, []);
|
|
1542
|
+
function register(key, T) {
|
|
1543
|
+
const instance = context.has(key, T, i => init.add(i));
|
|
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
|
+
if (Parent.get(value) === instance) {
|
|
1554
|
+
context.add(value);
|
|
1555
|
+
init.add(value);
|
|
1556
|
+
}
|
|
1557
|
+
});
|
|
1558
|
+
for (const apply of getPending(instance))
|
|
1559
|
+
apply(context);
|
|
1560
|
+
}
|
|
1561
|
+
React.useLayoutEffect(() => () => context.pop(), []);
|
|
1562
|
+
return context;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
class Global extends MVC {
|
|
1566
|
+
}
|
|
1567
|
+
Global.global = true;
|
|
1568
|
+
Global.keepAlive = true;
|
|
1569
|
+
|
|
1570
|
+
const LOCAL = "$debug local";
|
|
1571
|
+
const STATE = "$debug state";
|
|
1572
|
+
const UPDATE = "$debug update";
|
|
1573
|
+
const CONTROL = "$debug controller";
|
|
1574
|
+
defineProperties(Model.prototype, {
|
|
1575
|
+
[CONTROL]: {
|
|
1576
|
+
get() {
|
|
1577
|
+
return controller(this);
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
[LOCAL]: {
|
|
1581
|
+
get() {
|
|
1582
|
+
return subscriber(this);
|
|
1583
|
+
}
|
|
1584
|
+
},
|
|
1585
|
+
[STATE]: {
|
|
1586
|
+
get() {
|
|
1587
|
+
const { state } = controller(this);
|
|
1588
|
+
const output = {};
|
|
1589
|
+
state.forEach((value, key) => output[key] = value);
|
|
1590
|
+
return output;
|
|
1591
|
+
}
|
|
1592
|
+
},
|
|
1593
|
+
[UPDATE]: {
|
|
1594
|
+
get() {
|
|
1595
|
+
return (subscriber(this) || controller(this)).latest;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
const Debug = {
|
|
1600
|
+
CONTROL,
|
|
1601
|
+
LOCAL,
|
|
1602
|
+
STATE,
|
|
1603
|
+
UPDATE
|
|
1604
|
+
};
|
|
1605
|
+
|
|
1606
|
+
export { Consumer, Debug, Global, MVC, MVC as Model, Provider, add, MVC as default, get, has, ref, run, set, tap, use$1 as use, useContext, useNew, useTap };
|