@expressive/mvc 0.12.0 → 0.13.1
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 +5 -12
- package/lib/index.esm.js +204 -187
- package/lib/index.js +203 -186
- package/package.json +1 -1
package/lib/index.esm.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import React, { useState,
|
|
1
|
+
import React, { useState, Suspense } from 'react';
|
|
2
2
|
|
|
3
3
|
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
4
|
-
|
|
5
|
-
|
|
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;
|
|
6
15
|
}
|
|
7
16
|
|
|
8
17
|
class Issue extends Error {
|
|
@@ -161,7 +170,7 @@ const Oops$d = issues({
|
|
|
161
170
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
162
171
|
});
|
|
163
172
|
function createEffect(model, callback, keys) {
|
|
164
|
-
return
|
|
173
|
+
return control(model, controller => {
|
|
165
174
|
let unSet;
|
|
166
175
|
let busy = false;
|
|
167
176
|
function effect(value) {
|
|
@@ -186,7 +195,7 @@ function createEffect(model, callback, keys) {
|
|
|
186
195
|
}
|
|
187
196
|
if (Array.isArray(keys)) {
|
|
188
197
|
invoke();
|
|
189
|
-
return
|
|
198
|
+
return controller.addListener(key => {
|
|
190
199
|
if (key === null) {
|
|
191
200
|
if (!keys.length)
|
|
192
201
|
invoke();
|
|
@@ -195,7 +204,7 @@ function createEffect(model, callback, keys) {
|
|
|
195
204
|
return invoke;
|
|
196
205
|
});
|
|
197
206
|
}
|
|
198
|
-
const sub =
|
|
207
|
+
const sub = controller.subscribe(() => invoke);
|
|
199
208
|
model = sub.proxy;
|
|
200
209
|
invoke();
|
|
201
210
|
return sub.commit();
|
|
@@ -227,13 +236,13 @@ const Oops$c = issues({
|
|
|
227
236
|
function addEventListener(source, arg1, arg2, arg3) {
|
|
228
237
|
if (typeof arg1 == "string")
|
|
229
238
|
arg1 = [arg1];
|
|
230
|
-
return
|
|
239
|
+
return control(source, controller => {
|
|
231
240
|
for (const key of arg1)
|
|
232
241
|
try {
|
|
233
242
|
void source[key];
|
|
234
243
|
}
|
|
235
244
|
catch (e) { }
|
|
236
|
-
const removeListener =
|
|
245
|
+
const removeListener = controller.addListener(key => {
|
|
237
246
|
if (!key && !arg1.length)
|
|
238
247
|
arg2.call(source, []);
|
|
239
248
|
if (arg1.includes(key)) {
|
|
@@ -256,8 +265,8 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
256
265
|
removeListener();
|
|
257
266
|
reject(Oops$c.Timeout(k, message));
|
|
258
267
|
};
|
|
259
|
-
const removeListener =
|
|
260
|
-
const pending =
|
|
268
|
+
const removeListener = control(source, controller => {
|
|
269
|
+
const pending = controller.frame;
|
|
261
270
|
if (keys === null) {
|
|
262
271
|
if (pending.size)
|
|
263
272
|
reject(Oops$c.StrictNoUpdate());
|
|
@@ -284,8 +293,8 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
284
293
|
return;
|
|
285
294
|
}
|
|
286
295
|
else
|
|
287
|
-
|
|
288
|
-
return
|
|
296
|
+
controller.waiting.add(resolve);
|
|
297
|
+
return controller.addListener(key => {
|
|
289
298
|
if (!key) {
|
|
290
299
|
if (keys && !keys.length)
|
|
291
300
|
resolve([]);
|
|
@@ -294,7 +303,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
294
303
|
}
|
|
295
304
|
else if (!keys || keys.includes(key)) {
|
|
296
305
|
removeListener();
|
|
297
|
-
return keys => resolve(single ?
|
|
306
|
+
return keys => resolve(single ? controller.state.get(key) : keys);
|
|
298
307
|
}
|
|
299
308
|
});
|
|
300
309
|
});
|
|
@@ -311,35 +320,6 @@ class Subscriber {
|
|
|
311
320
|
this.active = false;
|
|
312
321
|
this.dependant = new Set();
|
|
313
322
|
this.watch = new Map();
|
|
314
|
-
this.commit = () => {
|
|
315
|
-
const release = this.parent.addListener(this.event);
|
|
316
|
-
this.active = true;
|
|
317
|
-
this.dependant.forEach(x => x.commit());
|
|
318
|
-
return this.release = () => {
|
|
319
|
-
this.dependant.forEach(x => x.release());
|
|
320
|
-
release();
|
|
321
|
-
};
|
|
322
|
-
};
|
|
323
|
-
this.event = (key) => {
|
|
324
|
-
if (!this.active)
|
|
325
|
-
return;
|
|
326
|
-
const { parent, watch } = this;
|
|
327
|
-
const handler = watch.get(key);
|
|
328
|
-
let notify;
|
|
329
|
-
if (typeof handler == "function") {
|
|
330
|
-
const callback = handler();
|
|
331
|
-
if (callback === true)
|
|
332
|
-
notify = this.onUpdate(key, parent);
|
|
333
|
-
}
|
|
334
|
-
else if (handler === true)
|
|
335
|
-
notify = this.onUpdate(key, parent);
|
|
336
|
-
if (!notify)
|
|
337
|
-
return;
|
|
338
|
-
parent.waiting.add(update => {
|
|
339
|
-
this.latest = update.filter(k => watch.has(k));
|
|
340
|
-
});
|
|
341
|
-
parent.waiting.add(notify);
|
|
342
|
-
};
|
|
343
323
|
const proxy = create(parent.subject);
|
|
344
324
|
const reset = () => this.latest = undefined;
|
|
345
325
|
REGISTER$1.set(proxy, this);
|
|
@@ -351,28 +331,45 @@ class Subscriber {
|
|
|
351
331
|
}
|
|
352
332
|
});
|
|
353
333
|
}
|
|
354
|
-
static get(from) {
|
|
355
|
-
return REGISTER$1.get(from);
|
|
356
|
-
}
|
|
357
334
|
get using() {
|
|
358
335
|
return Array.from(this.watch.keys());
|
|
359
336
|
}
|
|
360
|
-
assign(apply, keys) {
|
|
361
|
-
const { waiting, subject } = this.parent;
|
|
362
|
-
this.active = false;
|
|
363
|
-
if (typeof keys !== "object")
|
|
364
|
-
keys = getOwnPropertyNames(subject);
|
|
365
|
-
for (const key of keys)
|
|
366
|
-
if (key in apply)
|
|
367
|
-
subject[key] = apply[key];
|
|
368
|
-
waiting.add(() => this.active = true);
|
|
369
|
-
}
|
|
370
337
|
add(key, value) {
|
|
371
338
|
if (value !== undefined)
|
|
372
339
|
this.watch.set(key, value);
|
|
373
340
|
else if (!this.watch.has(key))
|
|
374
341
|
this.watch.set(key, true);
|
|
375
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);
|
|
376
373
|
}
|
|
377
374
|
|
|
378
375
|
const Oops$b = issues({
|
|
@@ -392,7 +389,7 @@ class Model {
|
|
|
392
389
|
return addEventListener(this.is, arg1, arg2, arg3);
|
|
393
390
|
}
|
|
394
391
|
get(arg1, arg2) {
|
|
395
|
-
const { state } =
|
|
392
|
+
const { state } = control(this);
|
|
396
393
|
const extract = typeof arg1 == "string"
|
|
397
394
|
? () => state.get(arg1)
|
|
398
395
|
: () => {
|
|
@@ -409,19 +406,20 @@ class Model {
|
|
|
409
406
|
return this.on(arg1, timeout).then(extract);
|
|
410
407
|
}
|
|
411
408
|
set(arg1, arg2) {
|
|
412
|
-
const
|
|
409
|
+
const controller = control(this);
|
|
410
|
+
const { state } = controller;
|
|
413
411
|
if (typeof arg1 == "object")
|
|
414
412
|
for (const key in arg1) {
|
|
415
|
-
if (arg2 === true || (arg2 ? arg2.includes(key) :
|
|
416
|
-
|
|
417
|
-
|
|
413
|
+
if (arg2 === true || (arg2 ? arg2.includes(key) : state.has(key))) {
|
|
414
|
+
state.set(key, arg1[key]);
|
|
415
|
+
controller.update(key);
|
|
418
416
|
}
|
|
419
417
|
}
|
|
420
418
|
else if (typeof arg1 == "string") {
|
|
421
|
-
|
|
419
|
+
controller.update(arg1);
|
|
422
420
|
if (1 in arguments) {
|
|
423
|
-
if (
|
|
424
|
-
|
|
421
|
+
if (state.has(arg1))
|
|
422
|
+
state.set(arg1, arg2);
|
|
425
423
|
else if (arg1 in this) {
|
|
426
424
|
const method = this[arg1];
|
|
427
425
|
if (typeof method == "function")
|
|
@@ -433,7 +431,7 @@ class Model {
|
|
|
433
431
|
then: (callback) => {
|
|
434
432
|
if (!callback)
|
|
435
433
|
throw Oops$b.NoChaining();
|
|
436
|
-
|
|
434
|
+
controller.waiting.add(callback);
|
|
437
435
|
}
|
|
438
436
|
};
|
|
439
437
|
}
|
|
@@ -441,7 +439,7 @@ class Model {
|
|
|
441
439
|
* Clean up side effects and mark this instance for garbage-collection.
|
|
442
440
|
*/
|
|
443
441
|
end() {
|
|
444
|
-
|
|
442
|
+
control(this).clear();
|
|
445
443
|
}
|
|
446
444
|
/**
|
|
447
445
|
* Creates a new instance of this controller.
|
|
@@ -452,7 +450,7 @@ class Model {
|
|
|
452
450
|
*/
|
|
453
451
|
static new(...args) {
|
|
454
452
|
const instance = new this(...args);
|
|
455
|
-
|
|
453
|
+
control(instance);
|
|
456
454
|
return instance;
|
|
457
455
|
}
|
|
458
456
|
/**
|
|
@@ -507,7 +505,7 @@ class Control {
|
|
|
507
505
|
enumerable: false,
|
|
508
506
|
set: this.ref(key),
|
|
509
507
|
get() {
|
|
510
|
-
const sub =
|
|
508
|
+
const sub = subscriber(this);
|
|
511
509
|
if (sub)
|
|
512
510
|
sub.add(key);
|
|
513
511
|
return state.get(key);
|
|
@@ -567,34 +565,34 @@ class Control {
|
|
|
567
565
|
this.followers.clear();
|
|
568
566
|
listeners.forEach(x => x(null, this));
|
|
569
567
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}
|
|
589
|
-
control.state = new Map();
|
|
590
|
-
for (const key in subject)
|
|
591
|
-
control.watch(key);
|
|
592
|
-
control.waiting = new Set();
|
|
593
|
-
for (const cb of waiting)
|
|
594
|
-
cb([]);
|
|
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
|
+
};
|
|
595
587
|
}
|
|
596
|
-
|
|
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([]);
|
|
597
594
|
}
|
|
595
|
+
return cb ? cb(control) : control;
|
|
598
596
|
}
|
|
599
597
|
|
|
600
598
|
const Parent = new WeakMap();
|
|
@@ -613,8 +611,8 @@ function getRecursive(key, from) {
|
|
|
613
611
|
if (reset)
|
|
614
612
|
reset();
|
|
615
613
|
const value = state.get(key);
|
|
616
|
-
if (
|
|
617
|
-
const child =
|
|
614
|
+
if (value && controller(value)) {
|
|
615
|
+
const child = control(value).subscribe(local.onUpdate);
|
|
618
616
|
if (local.active)
|
|
619
617
|
child.commit();
|
|
620
618
|
local.dependant.add(child);
|
|
@@ -634,24 +632,24 @@ function getRecursive(key, from) {
|
|
|
634
632
|
return context.get(local);
|
|
635
633
|
};
|
|
636
634
|
}
|
|
637
|
-
function setRecursive(
|
|
638
|
-
const { state, subject } =
|
|
635
|
+
function setRecursive(controller, key, initial) {
|
|
636
|
+
const { state, subject } = controller;
|
|
639
637
|
const Type = initial.constructor;
|
|
640
638
|
let get;
|
|
641
639
|
const onUpdate = (next) => {
|
|
642
640
|
state.set(key, next);
|
|
643
641
|
if (!(next instanceof Type))
|
|
644
642
|
throw Oops$a.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
645
|
-
get = getRecursive(key,
|
|
643
|
+
get = getRecursive(key, controller);
|
|
646
644
|
Parent.set(next, subject);
|
|
647
|
-
|
|
645
|
+
control(next);
|
|
648
646
|
return true;
|
|
649
647
|
};
|
|
650
648
|
onUpdate(initial);
|
|
651
649
|
defineProperty(subject, key, {
|
|
652
|
-
set:
|
|
650
|
+
set: controller.ref(key, onUpdate),
|
|
653
651
|
get() {
|
|
654
|
-
const local =
|
|
652
|
+
const local = subscriber(this);
|
|
655
653
|
if (local)
|
|
656
654
|
local.add(key);
|
|
657
655
|
return get(local);
|
|
@@ -699,7 +697,7 @@ function add(instruction, label) {
|
|
|
699
697
|
get() {
|
|
700
698
|
if (!state.has(key) && shouldSuspend)
|
|
701
699
|
throw suspend(control, key);
|
|
702
|
-
const local =
|
|
700
|
+
const local = subscriber(this);
|
|
703
701
|
if (local)
|
|
704
702
|
local.add(key);
|
|
705
703
|
return onGet
|
|
@@ -830,7 +828,7 @@ function get(arg0, arg1, arg2) {
|
|
|
830
828
|
let source = this;
|
|
831
829
|
let setter;
|
|
832
830
|
if (typeof arg0 == "function") {
|
|
833
|
-
|
|
831
|
+
let result = mayRetry(arg0.bind(subject, key, subject));
|
|
834
832
|
if (typeof result == "function")
|
|
835
833
|
setter = result;
|
|
836
834
|
else {
|
|
@@ -844,7 +842,7 @@ function get(arg0, arg1, arg2) {
|
|
|
844
842
|
}
|
|
845
843
|
else if (typeof arg1 == "function") {
|
|
846
844
|
// replace source controller in-case it is different
|
|
847
|
-
source =
|
|
845
|
+
source = control(arg0);
|
|
848
846
|
setter = arg1;
|
|
849
847
|
}
|
|
850
848
|
else
|
|
@@ -874,7 +872,7 @@ function ref(arg, mapper) {
|
|
|
874
872
|
if (typeof arg != "object")
|
|
875
873
|
value = createRef(this, key, arg);
|
|
876
874
|
else
|
|
877
|
-
|
|
875
|
+
control(arg).state.forEach((_val, key) => {
|
|
878
876
|
defineProperty(value, key, mapper ? {
|
|
879
877
|
configurable: true,
|
|
880
878
|
get() {
|
|
@@ -1085,7 +1083,7 @@ function use$1(input, argument) {
|
|
|
1085
1083
|
if (next) {
|
|
1086
1084
|
get = getRecursive(key, this);
|
|
1087
1085
|
Parent.set(next, subject);
|
|
1088
|
-
|
|
1086
|
+
control(next);
|
|
1089
1087
|
}
|
|
1090
1088
|
if (typeof argument == "function")
|
|
1091
1089
|
argument(next);
|
|
@@ -1165,9 +1163,6 @@ class Lookup {
|
|
|
1165
1163
|
constructor() {
|
|
1166
1164
|
this.table = new Map();
|
|
1167
1165
|
}
|
|
1168
|
-
get local() {
|
|
1169
|
-
return unique(getOwnPropertySymbols(this).map(symbol => this[symbol]));
|
|
1170
|
-
}
|
|
1171
1166
|
key(T) {
|
|
1172
1167
|
let key = this.table.get(T);
|
|
1173
1168
|
if (!key) {
|
|
@@ -1176,15 +1171,26 @@ class Lookup {
|
|
|
1176
1171
|
}
|
|
1177
1172
|
return key;
|
|
1178
1173
|
}
|
|
1179
|
-
get(
|
|
1180
|
-
return this[this.key(
|
|
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;
|
|
1181
1189
|
}
|
|
1182
1190
|
add(input) {
|
|
1183
1191
|
let writable = true;
|
|
1184
1192
|
let T;
|
|
1185
1193
|
let I;
|
|
1186
|
-
if (MVC.isTypeof(input) && input.global)
|
|
1187
|
-
return input.new();
|
|
1188
1194
|
if (typeof input == "function") {
|
|
1189
1195
|
T = input;
|
|
1190
1196
|
I = new input();
|
|
@@ -1196,10 +1202,9 @@ class Lookup {
|
|
|
1196
1202
|
}
|
|
1197
1203
|
do {
|
|
1198
1204
|
const key = this.key(T);
|
|
1199
|
-
const conflict = this.hasOwnProperty(key);
|
|
1200
1205
|
defineProperty(this, key, {
|
|
1201
|
-
value: conflict ? null : I,
|
|
1202
1206
|
configurable: true,
|
|
1207
|
+
value: this.hasOwnProperty(key) ? null : I,
|
|
1203
1208
|
writable
|
|
1204
1209
|
});
|
|
1205
1210
|
T = getPrototypeOf(T);
|
|
@@ -1207,7 +1212,9 @@ class Lookup {
|
|
|
1207
1212
|
return I;
|
|
1208
1213
|
}
|
|
1209
1214
|
push() {
|
|
1210
|
-
|
|
1215
|
+
const next = create(this);
|
|
1216
|
+
next.register = new Map();
|
|
1217
|
+
return next;
|
|
1211
1218
|
}
|
|
1212
1219
|
pop() {
|
|
1213
1220
|
const items = new Set();
|
|
@@ -1237,7 +1244,7 @@ const Pending = new WeakMap();
|
|
|
1237
1244
|
const Applied = new WeakMap();
|
|
1238
1245
|
function tap(type, argument) {
|
|
1239
1246
|
return add(function tap(key) {
|
|
1240
|
-
if (type.global)
|
|
1247
|
+
if (MVC.isTypeof(type) && type.global)
|
|
1241
1248
|
return {
|
|
1242
1249
|
recursive: true,
|
|
1243
1250
|
value: type.get()
|
|
@@ -1284,20 +1291,13 @@ function getPending(subject) {
|
|
|
1284
1291
|
return pending;
|
|
1285
1292
|
}
|
|
1286
1293
|
|
|
1287
|
-
function use(init) {
|
|
1288
|
-
const [state, update] = React.useState(() => [
|
|
1289
|
-
init(() => update(state.concat()))
|
|
1290
|
-
]);
|
|
1291
|
-
return state[0];
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
1294
|
function useNew(source, arg1, arg2) {
|
|
1295
1295
|
const instance = React.useMemo(() => {
|
|
1296
1296
|
const callback = arg2 || arg1;
|
|
1297
1297
|
const instance = Model.isTypeof(source)
|
|
1298
1298
|
? new source()
|
|
1299
1299
|
: source();
|
|
1300
|
-
|
|
1300
|
+
control(instance);
|
|
1301
1301
|
if (typeof callback == "function")
|
|
1302
1302
|
callback(instance);
|
|
1303
1303
|
return instance;
|
|
@@ -1315,9 +1315,22 @@ function useNew(source, arg1, arg2) {
|
|
|
1315
1315
|
}, []);
|
|
1316
1316
|
return instance;
|
|
1317
1317
|
}
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1320
|
-
|
|
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
|
+
}
|
|
1321
1334
|
React.useLayoutEffect(() => {
|
|
1322
1335
|
local.commit();
|
|
1323
1336
|
return () => {
|
|
@@ -1329,9 +1342,17 @@ function useNew(source, arg1, arg2) {
|
|
|
1329
1342
|
return local.proxy;
|
|
1330
1343
|
}
|
|
1331
1344
|
|
|
1332
|
-
function
|
|
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)];
|
|
1333
1354
|
const local = use(refresh => {
|
|
1334
|
-
const sub =
|
|
1355
|
+
const sub = control(source).subscribe(() => update);
|
|
1335
1356
|
const spy = sub.proxy;
|
|
1336
1357
|
let value = compute.call(spy, spy);
|
|
1337
1358
|
let update;
|
|
@@ -1380,30 +1401,30 @@ function useValue(source, compute, suspend) {
|
|
|
1380
1401
|
}
|
|
1381
1402
|
});
|
|
1382
1403
|
return sub;
|
|
1383
|
-
});
|
|
1384
|
-
React.useLayoutEffect(() => local.release,
|
|
1404
|
+
}, deps);
|
|
1405
|
+
React.useLayoutEffect(() => local.release, deps);
|
|
1385
1406
|
return local.proxy;
|
|
1386
1407
|
}
|
|
1387
1408
|
|
|
1388
1409
|
function useTap(source, arg1, arg2) {
|
|
1389
|
-
const instance =
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
const local = use(refresh => (
|
|
1401
|
-
React.useLayoutEffect(local.commit,
|
|
1402
|
-
if (
|
|
1410
|
+
const instance = typeof source == "object"
|
|
1411
|
+
? source
|
|
1412
|
+
: "get" in source
|
|
1413
|
+
? source.get()
|
|
1414
|
+
: useContext(source);
|
|
1415
|
+
return typeof arg1 == "function"
|
|
1416
|
+
? useCompute(instance, arg1, arg2)
|
|
1417
|
+
: useSubscribe(instance, arg1, arg2);
|
|
1418
|
+
}
|
|
1419
|
+
function useSubscribe(source, path, expect) {
|
|
1420
|
+
const deps = [uid(source)];
|
|
1421
|
+
const local = use(refresh => (control(source).subscribe(() => refresh)), deps);
|
|
1422
|
+
React.useLayoutEffect(() => local.commit(), deps);
|
|
1423
|
+
if (path === undefined)
|
|
1403
1424
|
return local.proxy;
|
|
1404
|
-
const value = local.proxy[
|
|
1405
|
-
if (value === undefined &&
|
|
1406
|
-
throw suspend(local.parent,
|
|
1425
|
+
const value = local.proxy[path];
|
|
1426
|
+
if (value === undefined && expect)
|
|
1427
|
+
throw suspend(local.parent, path);
|
|
1407
1428
|
return value;
|
|
1408
1429
|
}
|
|
1409
1430
|
|
|
@@ -1461,14 +1482,19 @@ class MVC extends Model {
|
|
|
1461
1482
|
callback(arg2);
|
|
1462
1483
|
return instance;
|
|
1463
1484
|
}
|
|
1464
|
-
static tap(
|
|
1465
|
-
|
|
1485
|
+
static tap(arg1, arg2) {
|
|
1486
|
+
const instance = this.get();
|
|
1487
|
+
return typeof arg1 == "function"
|
|
1488
|
+
? useCompute(instance, arg1, arg2)
|
|
1489
|
+
: useSubscribe(instance, arg1, arg2);
|
|
1466
1490
|
}
|
|
1467
1491
|
static use(a, b) {
|
|
1468
1492
|
return useNew(this, a, b);
|
|
1469
1493
|
}
|
|
1470
|
-
static meta(
|
|
1471
|
-
return
|
|
1494
|
+
static meta(arg1, arg2) {
|
|
1495
|
+
return typeof arg1 == "function"
|
|
1496
|
+
? useCompute(this, arg1, arg2)
|
|
1497
|
+
: useSubscribe(this, arg1, arg2);
|
|
1472
1498
|
}
|
|
1473
1499
|
}
|
|
1474
1500
|
|
|
@@ -1492,47 +1518,39 @@ const Oops = issues({
|
|
|
1492
1518
|
});
|
|
1493
1519
|
function Provider(props) {
|
|
1494
1520
|
const context = useNewContext(props.for, props.and);
|
|
1495
|
-
React.useLayoutEffect(() => () => context.pop(), []);
|
|
1496
1521
|
return (React.createElement(LookupContext.Provider, { value: context }, props.fallback === false
|
|
1497
1522
|
? props.children
|
|
1498
1523
|
: (React.createElement(Suspense, { fallback: props.fallback || null }, props.children))));
|
|
1499
1524
|
}
|
|
1500
1525
|
function useNewContext(include, assign) {
|
|
1526
|
+
const init = new Set();
|
|
1501
1527
|
const ambient = useLookup();
|
|
1502
1528
|
const context = React.useMemo(() => {
|
|
1503
1529
|
if (!include)
|
|
1504
1530
|
throw Oops.NoType();
|
|
1505
|
-
|
|
1506
|
-
function register(T) {
|
|
1507
|
-
const i = next.add(T);
|
|
1508
|
-
if (assign)
|
|
1509
|
-
assignWeak(i, assign);
|
|
1510
|
-
Control.for(i).state.forEach(value => {
|
|
1511
|
-
if (Parent.get(value) === i)
|
|
1512
|
-
next.add(value);
|
|
1513
|
-
});
|
|
1514
|
-
}
|
|
1515
|
-
if (include instanceof Model || typeof include == "function")
|
|
1516
|
-
register(include);
|
|
1517
|
-
else
|
|
1518
|
-
values(include).forEach(register);
|
|
1519
|
-
for (const instance of next.local)
|
|
1520
|
-
if (instance)
|
|
1521
|
-
for (const apply of getPending(instance))
|
|
1522
|
-
apply(next);
|
|
1523
|
-
return next;
|
|
1531
|
+
return ambient.push();
|
|
1524
1532
|
}, []);
|
|
1525
|
-
|
|
1526
|
-
context.
|
|
1527
|
-
|
|
1528
|
-
|
|
1533
|
+
function register(key, T) {
|
|
1534
|
+
const instance = context.has(key, T, i => init.add(i));
|
|
1535
|
+
if (assign)
|
|
1536
|
+
assignWeak(instance, assign);
|
|
1537
|
+
}
|
|
1538
|
+
if (typeof include == "function" || include instanceof Model)
|
|
1539
|
+
register(0, include);
|
|
1540
|
+
else
|
|
1541
|
+
entries(include).forEach(e => register(...e));
|
|
1542
|
+
for (const instance of init) {
|
|
1543
|
+
control(instance).state.forEach(value => {
|
|
1544
|
+
if (Parent.get(value) === instance) {
|
|
1545
|
+
context.add(value);
|
|
1546
|
+
init.add(value);
|
|
1547
|
+
}
|
|
1529
1548
|
});
|
|
1549
|
+
for (const apply of getPending(instance))
|
|
1550
|
+
apply(context);
|
|
1551
|
+
}
|
|
1552
|
+
React.useLayoutEffect(() => () => context.pop(), []);
|
|
1530
1553
|
return context;
|
|
1531
|
-
}
|
|
1532
|
-
function assignWeak(into, from) {
|
|
1533
|
-
for (const K in from)
|
|
1534
|
-
if (K in into)
|
|
1535
|
-
into[K] = from[K];
|
|
1536
1554
|
}
|
|
1537
1555
|
|
|
1538
1556
|
class Global extends MVC {
|
|
@@ -1547,17 +1565,17 @@ const CONTROL = "$debug controller";
|
|
|
1547
1565
|
defineProperties(Model.prototype, {
|
|
1548
1566
|
[CONTROL]: {
|
|
1549
1567
|
get() {
|
|
1550
|
-
return
|
|
1568
|
+
return controller(this);
|
|
1551
1569
|
}
|
|
1552
1570
|
},
|
|
1553
1571
|
[LOCAL]: {
|
|
1554
1572
|
get() {
|
|
1555
|
-
return
|
|
1573
|
+
return subscriber(this);
|
|
1556
1574
|
}
|
|
1557
1575
|
},
|
|
1558
1576
|
[STATE]: {
|
|
1559
1577
|
get() {
|
|
1560
|
-
const { state } =
|
|
1578
|
+
const { state } = controller(this);
|
|
1561
1579
|
const output = {};
|
|
1562
1580
|
state.forEach((value, key) => output[key] = value);
|
|
1563
1581
|
return output;
|
|
@@ -1565,8 +1583,7 @@ defineProperties(Model.prototype, {
|
|
|
1565
1583
|
},
|
|
1566
1584
|
[UPDATE]: {
|
|
1567
1585
|
get() {
|
|
1568
|
-
|
|
1569
|
-
return source && source.latest;
|
|
1586
|
+
return (subscriber(this) || controller(this)).latest;
|
|
1570
1587
|
}
|
|
1571
1588
|
}
|
|
1572
1589
|
});
|