@expressive/mvc 0.9.2 → 0.9.4
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 +40 -36
- package/lib/index.esm.js +118 -98
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +118 -98
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -29,6 +29,32 @@ declare class Subscriber<T extends {} = any> {
|
|
|
29
29
|
private event;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
declare const LOCAL = "$debug local";
|
|
33
|
+
declare const STATE = "$debug state";
|
|
34
|
+
declare const UPDATE = "$debug update";
|
|
35
|
+
declare const CONTROL = "$debug controller";
|
|
36
|
+
declare const Debug: {
|
|
37
|
+
readonly CONTROL: "$debug controller";
|
|
38
|
+
readonly LOCAL: "$debug local";
|
|
39
|
+
readonly STATE: "$debug state";
|
|
40
|
+
readonly UPDATE: "$debug update";
|
|
41
|
+
};
|
|
42
|
+
declare type Debug<T extends {}> = T & {
|
|
43
|
+
/** Controller for this instance. */
|
|
44
|
+
[CONTROL]?: Control<T>;
|
|
45
|
+
/** Current subscriber (if present) while used in a live context (e.g. hook or effect). */
|
|
46
|
+
[LOCAL]?: Subscriber<T>;
|
|
47
|
+
/** Current state of this instance. */
|
|
48
|
+
[STATE]?: Model.Values<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Last update causing a refresh to subscribers.
|
|
51
|
+
*
|
|
52
|
+
* If accessed directly, will contain all keys from last push.
|
|
53
|
+
* If within a subscribed function, will contain only keys which explicitly caused a refresh.
|
|
54
|
+
*/
|
|
55
|
+
[UPDATE]?: readonly Model.Event<T>[];
|
|
56
|
+
};
|
|
57
|
+
|
|
32
58
|
declare namespace Model {
|
|
33
59
|
export { Control };
|
|
34
60
|
export { Subscriber };
|
|
@@ -52,7 +78,7 @@ declare namespace Model {
|
|
|
52
78
|
*
|
|
53
79
|
* TODO: Should exclude methods
|
|
54
80
|
**/
|
|
55
|
-
export type Field<T, U extends Model = Model> = Exclude<keyof T
|
|
81
|
+
export type Field<T, U extends Model = Model> = Exclude<keyof T, keyof U | keyof Debug<{}>> & string;
|
|
56
82
|
/**
|
|
57
83
|
* Including but not limited to `keyof T` which are not methods or defined by base Model.
|
|
58
84
|
**/
|
|
@@ -415,12 +441,13 @@ declare class MVC extends Model {
|
|
|
415
441
|
* **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
|
|
416
442
|
*/
|
|
417
443
|
static tap<T extends MVC>(this: Model.Type<T>): T;
|
|
418
|
-
static tap<
|
|
419
|
-
static tap<
|
|
420
|
-
static tap<T
|
|
421
|
-
static tap<T
|
|
422
|
-
static tap<T
|
|
423
|
-
static tap<T
|
|
444
|
+
static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
|
|
445
|
+
static tap<T extends MVC, K extends Model.Field<T>>(this: Model.Type<T>, key: K, expect?: boolean): T[K];
|
|
446
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => () => R): R;
|
|
447
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => (() => R) | null): R | null;
|
|
448
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
|
|
449
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
|
|
450
|
+
static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => R, expect?: boolean): R;
|
|
424
451
|
static use<I extends MVC>(this: Model.Type<I>, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
|
|
425
452
|
static use<I extends MVC>(this: Model.Type<I>, callback?: (instance: I) => void): I;
|
|
426
453
|
static use<I extends MVC>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
@@ -433,32 +460,6 @@ declare class MVC extends Model {
|
|
|
433
460
|
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
|
|
434
461
|
}
|
|
435
462
|
|
|
436
|
-
declare const LOCAL = "$debug local";
|
|
437
|
-
declare const STATE = "$debug state";
|
|
438
|
-
declare const UPDATE = "$debug update";
|
|
439
|
-
declare const CONTROL = "$debug controller";
|
|
440
|
-
declare const Debug: {
|
|
441
|
-
readonly CONTROL: "$debug controller";
|
|
442
|
-
readonly LOCAL: "$debug local";
|
|
443
|
-
readonly STATE: "$debug state";
|
|
444
|
-
readonly UPDATE: "$debug update";
|
|
445
|
-
};
|
|
446
|
-
declare type Debug<T extends {}> = T & {
|
|
447
|
-
/** Controller for this instance. */
|
|
448
|
-
[CONTROL]?: Control<T>;
|
|
449
|
-
/** Current subscriber (if present) while used in a live context (e.g. hook or effect). */
|
|
450
|
-
[LOCAL]?: Subscriber<T>;
|
|
451
|
-
/** Current state of this instance. */
|
|
452
|
-
[STATE]?: Model.Values<T>;
|
|
453
|
-
/**
|
|
454
|
-
* Last update causing a refresh to subscribers.
|
|
455
|
-
*
|
|
456
|
-
* If accessed directly, will contain all keys from last push.
|
|
457
|
-
* If within a subscribed function, will contain only keys which explicitly caused a refresh.
|
|
458
|
-
*/
|
|
459
|
-
[UPDATE]?: readonly Model.Event<T>[];
|
|
460
|
-
};
|
|
461
|
-
|
|
462
463
|
declare namespace Consumer {
|
|
463
464
|
type HasProps<E extends Class> = {
|
|
464
465
|
/** @deprecated - use for instead */
|
|
@@ -538,7 +539,7 @@ declare class Global extends MVC {
|
|
|
538
539
|
* Returns a thenable; resolves after successful update.
|
|
539
540
|
* If instance does not already exist, one will be created.
|
|
540
541
|
*/
|
|
541
|
-
static set<T extends typeof Global>(this: T, values: Model.Compat<InstanceOf<T>, Global>): PromiseLike<
|
|
542
|
+
static set<T extends typeof Global>(this: T, values: Model.Compat<InstanceOf<T>, Global>): PromiseLike<Model.Field<InstanceOf<T>, Global>[]>;
|
|
542
543
|
/**
|
|
543
544
|
* **React Hook** - Fetch most instance of this controller from context, if it exists.
|
|
544
545
|
*
|
|
@@ -597,7 +598,10 @@ declare namespace useTap {
|
|
|
597
598
|
declare function useTap<T extends Model>(source: useTap.Source<T>): T;
|
|
598
599
|
declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect: true): Exclude<T[K], undefined>;
|
|
599
600
|
declare function useTap<T extends Model, K extends Model.Field<T>>(source: useTap.Source<T>, path: K, expect?: boolean): T[K];
|
|
600
|
-
declare function useTap<T extends Model, R>(source: useTap.Source<T>,
|
|
601
|
-
declare function useTap<T extends Model, R>(source: useTap.Source<T>,
|
|
601
|
+
declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => () => R): R;
|
|
602
|
+
declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => (() => R) | null): R | null;
|
|
603
|
+
declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
|
|
604
|
+
declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): R | undefined;
|
|
605
|
+
declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => R, expect?: boolean): R;
|
|
602
606
|
|
|
603
607
|
export { Consumer, Debug, Global, MVC, MVC as Model, Provider, add, MVC as default, get, has, ref, run, set, tap, use, useContext, useModel, useTap, useValue };
|
package/lib/index.esm.js
CHANGED
|
@@ -19,11 +19,11 @@ function issues(register) {
|
|
|
19
19
|
|
|
20
20
|
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
21
21
|
|
|
22
|
-
const Oops$
|
|
22
|
+
const Oops$e = issues({
|
|
23
23
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
24
24
|
});
|
|
25
25
|
function suspend(source, key) {
|
|
26
|
-
const error = Oops$
|
|
26
|
+
const error = Oops$e.NotReady(source.subject, key);
|
|
27
27
|
const promise = new Promise(resolve => {
|
|
28
28
|
const release = source.addListener(forKey => {
|
|
29
29
|
if (forKey == key)
|
|
@@ -63,7 +63,7 @@ function mayRetry(fn) {
|
|
|
63
63
|
return compute();
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const Oops$
|
|
66
|
+
const Oops$d = issues({
|
|
67
67
|
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
68
68
|
});
|
|
69
69
|
const INFO = new WeakMap();
|
|
@@ -83,7 +83,7 @@ function computeMode(self, source, setter, key, required) {
|
|
|
83
83
|
return setter.call(sub.proxy, sub.proxy);
|
|
84
84
|
}
|
|
85
85
|
catch (err) {
|
|
86
|
-
Oops$
|
|
86
|
+
Oops$d.Failed(subject, key, initial).warn();
|
|
87
87
|
throw err;
|
|
88
88
|
}
|
|
89
89
|
};
|
|
@@ -110,6 +110,7 @@ function computeMode(self, source, setter, key, required) {
|
|
|
110
110
|
else
|
|
111
111
|
pending.add(refresh);
|
|
112
112
|
});
|
|
113
|
+
sub.watch.set(key, false);
|
|
113
114
|
try {
|
|
114
115
|
const value = compute(true);
|
|
115
116
|
state.set(key, value);
|
|
@@ -457,7 +458,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
457
458
|
});
|
|
458
459
|
}
|
|
459
460
|
|
|
460
|
-
const Oops$
|
|
461
|
+
const Oops$c = issues({
|
|
461
462
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
462
463
|
});
|
|
463
464
|
function run(task) {
|
|
@@ -465,7 +466,7 @@ function run(task) {
|
|
|
465
466
|
let pending = false;
|
|
466
467
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
467
468
|
if (pending)
|
|
468
|
-
return Promise.reject(Oops$
|
|
469
|
+
return Promise.reject(Oops$c.DuplicatePending(key));
|
|
469
470
|
pending = true;
|
|
470
471
|
this.update(key);
|
|
471
472
|
try {
|
|
@@ -487,7 +488,7 @@ function run(task) {
|
|
|
487
488
|
});
|
|
488
489
|
}
|
|
489
490
|
|
|
490
|
-
const Oops$
|
|
491
|
+
const Oops$b = issues({
|
|
491
492
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
492
493
|
});
|
|
493
494
|
function factoryMode(self, output, key, required) {
|
|
@@ -511,7 +512,7 @@ function factoryMode(self, output, key, required) {
|
|
|
511
512
|
const suspend = () => {
|
|
512
513
|
if (required === false)
|
|
513
514
|
return undefined;
|
|
514
|
-
const issue = Oops$
|
|
515
|
+
const issue = Oops$b.NotReady(subject, key);
|
|
515
516
|
assign(pending, {
|
|
516
517
|
message: issue.message,
|
|
517
518
|
stack: issue.stack
|
|
@@ -528,7 +529,7 @@ function factoryMode(self, output, key, required) {
|
|
|
528
529
|
};
|
|
529
530
|
}
|
|
530
531
|
|
|
531
|
-
const Oops$
|
|
532
|
+
const Oops$a = issues({
|
|
532
533
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
533
534
|
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
534
535
|
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
@@ -541,7 +542,7 @@ function get(arg0, arg1, arg2) {
|
|
|
541
542
|
let getter;
|
|
542
543
|
// Easy mistake, using a peer, will always be unresolved.
|
|
543
544
|
if (typeof arg0 == "symbol")
|
|
544
|
-
throw Oops$
|
|
545
|
+
throw Oops$a.PeerNotAllowed(subject, key);
|
|
545
546
|
// if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
546
547
|
// throw Oops.BadSource(subject, key, arg0);
|
|
547
548
|
this.state.set(key, undefined);
|
|
@@ -575,7 +576,7 @@ function get(arg0, arg1, arg2) {
|
|
|
575
576
|
init();
|
|
576
577
|
}
|
|
577
578
|
catch (err) {
|
|
578
|
-
Oops$
|
|
579
|
+
Oops$a.ComputeFailed(subject, key).warn();
|
|
579
580
|
throw err;
|
|
580
581
|
}
|
|
581
582
|
return () => {
|
|
@@ -586,7 +587,7 @@ function get(arg0, arg1, arg2) {
|
|
|
586
587
|
});
|
|
587
588
|
}
|
|
588
589
|
|
|
589
|
-
const Oops$
|
|
590
|
+
const Oops$9 = issues({
|
|
590
591
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
591
592
|
});
|
|
592
593
|
function createEffect(model, callback, keys) {
|
|
@@ -600,7 +601,7 @@ function createEffect(model, callback, keys) {
|
|
|
600
601
|
if (unSet instanceof Promise)
|
|
601
602
|
unSet = undefined;
|
|
602
603
|
if (unSet && typeof unSet !== "function")
|
|
603
|
-
throw Oops$
|
|
604
|
+
throw Oops$9.BadCallback();
|
|
604
605
|
}
|
|
605
606
|
function invoke() {
|
|
606
607
|
if (busy)
|
|
@@ -643,7 +644,7 @@ function createValueEffect(callback) {
|
|
|
643
644
|
if (typeof out == "function")
|
|
644
645
|
unSet = out;
|
|
645
646
|
else
|
|
646
|
-
throw Oops$
|
|
647
|
+
throw Oops$9.BadCallback();
|
|
647
648
|
};
|
|
648
649
|
}
|
|
649
650
|
|
|
@@ -841,7 +842,7 @@ function createProxy(emit, watch) {
|
|
|
841
842
|
}
|
|
842
843
|
|
|
843
844
|
const Parent = new WeakMap();
|
|
844
|
-
const Oops$
|
|
845
|
+
const Oops$8 = issues({
|
|
845
846
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
846
847
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
847
848
|
});
|
|
@@ -858,7 +859,7 @@ function use$1(input, argument) {
|
|
|
858
859
|
input = new input();
|
|
859
860
|
}
|
|
860
861
|
else if (input && typeof input !== "object")
|
|
861
|
-
throw Oops$
|
|
862
|
+
throw Oops$8.BadArgument(typeof input);
|
|
862
863
|
if (input instanceof Map || input instanceof Set)
|
|
863
864
|
return keyed(this, key, input);
|
|
864
865
|
const onUpdate = (next) => {
|
|
@@ -875,7 +876,7 @@ function use$1(input, argument) {
|
|
|
875
876
|
const suspend = () => {
|
|
876
877
|
if (required === false)
|
|
877
878
|
return;
|
|
878
|
-
const issue = Oops$
|
|
879
|
+
const issue = Oops$8.NotReady(subject, key);
|
|
879
880
|
assign(pending, {
|
|
880
881
|
message: issue.message,
|
|
881
882
|
stack: issue.stack
|
|
@@ -920,7 +921,7 @@ function use$1(input, argument) {
|
|
|
920
921
|
});
|
|
921
922
|
}
|
|
922
923
|
|
|
923
|
-
const Oops$
|
|
924
|
+
const Oops$7 = issues({
|
|
924
925
|
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
925
926
|
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
926
927
|
});
|
|
@@ -931,19 +932,100 @@ function has(Type, required) {
|
|
|
931
932
|
const expected = Type.name;
|
|
932
933
|
if (!value) {
|
|
933
934
|
if (required !== false)
|
|
934
|
-
throw Oops$
|
|
935
|
+
throw Oops$7.Required(expected, child);
|
|
935
936
|
}
|
|
936
937
|
else if (!(value instanceof Type))
|
|
937
|
-
throw Oops$
|
|
938
|
+
throw Oops$7.Unexpected(expected, child, value);
|
|
938
939
|
return { value };
|
|
939
940
|
});
|
|
940
941
|
}
|
|
941
942
|
|
|
942
|
-
const Oops$
|
|
943
|
+
const Oops$6 = issues({
|
|
943
944
|
Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
|
|
944
945
|
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
945
946
|
StrictUpdate: () => `Expected update but none in progress.`,
|
|
946
|
-
StrictNoUpdate: () => `Update is not expected but one is in progress
|
|
947
|
+
StrictNoUpdate: () => `Update is not expected but one is in progress!`
|
|
948
|
+
});
|
|
949
|
+
function addEventListener(source, arg1, arg2, arg3) {
|
|
950
|
+
const single = typeof arg1 == "string";
|
|
951
|
+
const keys = typeof arg1 == "string" ? [arg1] :
|
|
952
|
+
typeof arg1 == "object" ? arg1 :
|
|
953
|
+
undefined;
|
|
954
|
+
if (typeof arg2 == "function" && keys)
|
|
955
|
+
return Control.for(source, control => {
|
|
956
|
+
for (const key of keys)
|
|
957
|
+
try {
|
|
958
|
+
void source[key];
|
|
959
|
+
}
|
|
960
|
+
catch (e) { }
|
|
961
|
+
const invoke = single
|
|
962
|
+
? () => arg2.call(source, control.state.get(arg1), arg1)
|
|
963
|
+
: (frame) => arg2.call(source, frame);
|
|
964
|
+
const removeListener = control.addListener(key => {
|
|
965
|
+
if (!key && !keys.length)
|
|
966
|
+
invoke([]);
|
|
967
|
+
if (keys.includes(key)) {
|
|
968
|
+
if (arg3)
|
|
969
|
+
removeListener();
|
|
970
|
+
return invoke;
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
return removeListener;
|
|
974
|
+
});
|
|
975
|
+
return new Promise((resolve, reject) => {
|
|
976
|
+
const timeout = (message) => {
|
|
977
|
+
const k = keys ? keys.join(", ") : "any";
|
|
978
|
+
removeListener();
|
|
979
|
+
reject(Oops$6.Timeout(k, message));
|
|
980
|
+
};
|
|
981
|
+
const removeListener = Control.for(source, control => {
|
|
982
|
+
const pending = control.frame;
|
|
983
|
+
if (keys === null) {
|
|
984
|
+
if (pending.size)
|
|
985
|
+
reject(Oops$6.StrictNoUpdate());
|
|
986
|
+
else
|
|
987
|
+
resolve(null);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
if (keys) {
|
|
991
|
+
if (keys.length) {
|
|
992
|
+
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
993
|
+
reject(Oops$6.KeysExpected(keys[0]));
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
else
|
|
997
|
+
for (const key of keys)
|
|
998
|
+
try {
|
|
999
|
+
void source[key];
|
|
1000
|
+
}
|
|
1001
|
+
catch (e) { }
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
1005
|
+
reject(Oops$6.StrictUpdate());
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
else
|
|
1009
|
+
control.waiting.add(resolve);
|
|
1010
|
+
return control.addListener(key => {
|
|
1011
|
+
if (!key) {
|
|
1012
|
+
if (keys && !keys.length)
|
|
1013
|
+
resolve([]);
|
|
1014
|
+
else
|
|
1015
|
+
timeout(`lifetime of ${source}`);
|
|
1016
|
+
}
|
|
1017
|
+
else if (!keys || keys.includes(key)) {
|
|
1018
|
+
removeListener();
|
|
1019
|
+
return keys => resolve(single ? control.state.get(key) : keys);
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
if (arg2 && typeof arg2 == "number")
|
|
1024
|
+
setTimeout(() => timeout(`${arg2}ms`), arg2);
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
const Oops$5 = issues({
|
|
947
1029
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
948
1030
|
});
|
|
949
1031
|
class Model {
|
|
@@ -954,82 +1036,7 @@ class Model {
|
|
|
954
1036
|
on(arg1, arg2, arg3) {
|
|
955
1037
|
if (typeof arg1 == "function")
|
|
956
1038
|
return createEffect(this.is, arg1, arg2);
|
|
957
|
-
|
|
958
|
-
const keys = typeof arg1 == "string" ? [arg1] :
|
|
959
|
-
typeof arg1 == "object" ? arg1 :
|
|
960
|
-
undefined;
|
|
961
|
-
if (typeof arg2 == "function" && keys)
|
|
962
|
-
return Control.for(this, control => {
|
|
963
|
-
for (const key of keys)
|
|
964
|
-
try {
|
|
965
|
-
void this[key];
|
|
966
|
-
}
|
|
967
|
-
catch (e) { }
|
|
968
|
-
const invoke = single
|
|
969
|
-
? () => arg2.call(this, control.state.get(arg1), arg1)
|
|
970
|
-
: (frame) => arg2.call(this, frame);
|
|
971
|
-
const removeListener = control.addListener(key => {
|
|
972
|
-
if (!key && !keys.length)
|
|
973
|
-
invoke([]);
|
|
974
|
-
if (keys.includes(key)) {
|
|
975
|
-
if (arg3)
|
|
976
|
-
removeListener();
|
|
977
|
-
return invoke;
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
return removeListener;
|
|
981
|
-
});
|
|
982
|
-
return new Promise((resolve, reject) => {
|
|
983
|
-
const timeout = (message) => {
|
|
984
|
-
const k = keys ? keys.join(", ") : "any";
|
|
985
|
-
removeListener();
|
|
986
|
-
reject(Oops$5.Timeout(k, message));
|
|
987
|
-
};
|
|
988
|
-
const removeListener = Control.for(this, control => {
|
|
989
|
-
const pending = control.frame;
|
|
990
|
-
if (keys === null) {
|
|
991
|
-
if (pending.size)
|
|
992
|
-
reject(Oops$5.StrictNoUpdate());
|
|
993
|
-
else
|
|
994
|
-
resolve(null);
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
if (keys) {
|
|
998
|
-
if (keys.length) {
|
|
999
|
-
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
1000
|
-
reject(Oops$5.KeysExpected(keys[0]));
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
else
|
|
1004
|
-
for (const key of keys)
|
|
1005
|
-
try {
|
|
1006
|
-
void this[key];
|
|
1007
|
-
}
|
|
1008
|
-
catch (e) { }
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
1012
|
-
reject(Oops$5.StrictUpdate());
|
|
1013
|
-
return;
|
|
1014
|
-
}
|
|
1015
|
-
else
|
|
1016
|
-
control.waiting.add(resolve);
|
|
1017
|
-
return control.addListener(key => {
|
|
1018
|
-
if (!key) {
|
|
1019
|
-
if (keys && !keys.length)
|
|
1020
|
-
resolve([]);
|
|
1021
|
-
else
|
|
1022
|
-
timeout(`lifetime of ${this}`);
|
|
1023
|
-
}
|
|
1024
|
-
else if (!keys || keys.includes(key)) {
|
|
1025
|
-
removeListener();
|
|
1026
|
-
return keys => resolve(single ? control.state.get(key) : keys);
|
|
1027
|
-
}
|
|
1028
|
-
});
|
|
1029
|
-
});
|
|
1030
|
-
if (arg2 && typeof arg2 == "number")
|
|
1031
|
-
setTimeout(() => timeout(`${arg2}ms`), arg2);
|
|
1032
|
-
});
|
|
1039
|
+
return addEventListener(this.is, arg1, arg2, arg3);
|
|
1033
1040
|
}
|
|
1034
1041
|
export(subset) {
|
|
1035
1042
|
const { state } = Control.for(this);
|
|
@@ -1282,6 +1289,19 @@ function useValue(source, compute, suspend) {
|
|
|
1282
1289
|
else
|
|
1283
1290
|
refresh();
|
|
1284
1291
|
};
|
|
1292
|
+
if (value === null) {
|
|
1293
|
+
sub.watch.clear();
|
|
1294
|
+
return {
|
|
1295
|
+
proxy: null,
|
|
1296
|
+
release: () => { }
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
if (typeof value == "function") {
|
|
1300
|
+
const get = value;
|
|
1301
|
+
sub.watch.clear();
|
|
1302
|
+
compute = () => get();
|
|
1303
|
+
value = get();
|
|
1304
|
+
}
|
|
1285
1305
|
if (value instanceof Promise) {
|
|
1286
1306
|
value.then(set);
|
|
1287
1307
|
value = undefined;
|