@expressive/mvc 0.9.3 → 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 +117 -98
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +117 -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
|
};
|
|
@@ -458,7 +458,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
|
|
461
|
-
const Oops$
|
|
461
|
+
const Oops$c = issues({
|
|
462
462
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
463
463
|
});
|
|
464
464
|
function run(task) {
|
|
@@ -466,7 +466,7 @@ function run(task) {
|
|
|
466
466
|
let pending = false;
|
|
467
467
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
468
468
|
if (pending)
|
|
469
|
-
return Promise.reject(Oops$
|
|
469
|
+
return Promise.reject(Oops$c.DuplicatePending(key));
|
|
470
470
|
pending = true;
|
|
471
471
|
this.update(key);
|
|
472
472
|
try {
|
|
@@ -488,7 +488,7 @@ function run(task) {
|
|
|
488
488
|
});
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
const Oops$
|
|
491
|
+
const Oops$b = issues({
|
|
492
492
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
493
493
|
});
|
|
494
494
|
function factoryMode(self, output, key, required) {
|
|
@@ -512,7 +512,7 @@ function factoryMode(self, output, key, required) {
|
|
|
512
512
|
const suspend = () => {
|
|
513
513
|
if (required === false)
|
|
514
514
|
return undefined;
|
|
515
|
-
const issue = Oops$
|
|
515
|
+
const issue = Oops$b.NotReady(subject, key);
|
|
516
516
|
assign(pending, {
|
|
517
517
|
message: issue.message,
|
|
518
518
|
stack: issue.stack
|
|
@@ -529,7 +529,7 @@ function factoryMode(self, output, key, required) {
|
|
|
529
529
|
};
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
-
const Oops$
|
|
532
|
+
const Oops$a = issues({
|
|
533
533
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
534
534
|
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
535
535
|
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
@@ -542,7 +542,7 @@ function get(arg0, arg1, arg2) {
|
|
|
542
542
|
let getter;
|
|
543
543
|
// Easy mistake, using a peer, will always be unresolved.
|
|
544
544
|
if (typeof arg0 == "symbol")
|
|
545
|
-
throw Oops$
|
|
545
|
+
throw Oops$a.PeerNotAllowed(subject, key);
|
|
546
546
|
// if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
547
547
|
// throw Oops.BadSource(subject, key, arg0);
|
|
548
548
|
this.state.set(key, undefined);
|
|
@@ -576,7 +576,7 @@ function get(arg0, arg1, arg2) {
|
|
|
576
576
|
init();
|
|
577
577
|
}
|
|
578
578
|
catch (err) {
|
|
579
|
-
Oops$
|
|
579
|
+
Oops$a.ComputeFailed(subject, key).warn();
|
|
580
580
|
throw err;
|
|
581
581
|
}
|
|
582
582
|
return () => {
|
|
@@ -587,7 +587,7 @@ function get(arg0, arg1, arg2) {
|
|
|
587
587
|
});
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
-
const Oops$
|
|
590
|
+
const Oops$9 = issues({
|
|
591
591
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
592
592
|
});
|
|
593
593
|
function createEffect(model, callback, keys) {
|
|
@@ -601,7 +601,7 @@ function createEffect(model, callback, keys) {
|
|
|
601
601
|
if (unSet instanceof Promise)
|
|
602
602
|
unSet = undefined;
|
|
603
603
|
if (unSet && typeof unSet !== "function")
|
|
604
|
-
throw Oops$
|
|
604
|
+
throw Oops$9.BadCallback();
|
|
605
605
|
}
|
|
606
606
|
function invoke() {
|
|
607
607
|
if (busy)
|
|
@@ -644,7 +644,7 @@ function createValueEffect(callback) {
|
|
|
644
644
|
if (typeof out == "function")
|
|
645
645
|
unSet = out;
|
|
646
646
|
else
|
|
647
|
-
throw Oops$
|
|
647
|
+
throw Oops$9.BadCallback();
|
|
648
648
|
};
|
|
649
649
|
}
|
|
650
650
|
|
|
@@ -842,7 +842,7 @@ function createProxy(emit, watch) {
|
|
|
842
842
|
}
|
|
843
843
|
|
|
844
844
|
const Parent = new WeakMap();
|
|
845
|
-
const Oops$
|
|
845
|
+
const Oops$8 = issues({
|
|
846
846
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
847
847
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
848
848
|
});
|
|
@@ -859,7 +859,7 @@ function use$1(input, argument) {
|
|
|
859
859
|
input = new input();
|
|
860
860
|
}
|
|
861
861
|
else if (input && typeof input !== "object")
|
|
862
|
-
throw Oops$
|
|
862
|
+
throw Oops$8.BadArgument(typeof input);
|
|
863
863
|
if (input instanceof Map || input instanceof Set)
|
|
864
864
|
return keyed(this, key, input);
|
|
865
865
|
const onUpdate = (next) => {
|
|
@@ -876,7 +876,7 @@ function use$1(input, argument) {
|
|
|
876
876
|
const suspend = () => {
|
|
877
877
|
if (required === false)
|
|
878
878
|
return;
|
|
879
|
-
const issue = Oops$
|
|
879
|
+
const issue = Oops$8.NotReady(subject, key);
|
|
880
880
|
assign(pending, {
|
|
881
881
|
message: issue.message,
|
|
882
882
|
stack: issue.stack
|
|
@@ -921,7 +921,7 @@ function use$1(input, argument) {
|
|
|
921
921
|
});
|
|
922
922
|
}
|
|
923
923
|
|
|
924
|
-
const Oops$
|
|
924
|
+
const Oops$7 = issues({
|
|
925
925
|
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
926
926
|
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
927
927
|
});
|
|
@@ -932,19 +932,100 @@ function has(Type, required) {
|
|
|
932
932
|
const expected = Type.name;
|
|
933
933
|
if (!value) {
|
|
934
934
|
if (required !== false)
|
|
935
|
-
throw Oops$
|
|
935
|
+
throw Oops$7.Required(expected, child);
|
|
936
936
|
}
|
|
937
937
|
else if (!(value instanceof Type))
|
|
938
|
-
throw Oops$
|
|
938
|
+
throw Oops$7.Unexpected(expected, child, value);
|
|
939
939
|
return { value };
|
|
940
940
|
});
|
|
941
941
|
}
|
|
942
942
|
|
|
943
|
-
const Oops$
|
|
943
|
+
const Oops$6 = issues({
|
|
944
944
|
Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
|
|
945
945
|
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
946
946
|
StrictUpdate: () => `Expected update but none in progress.`,
|
|
947
|
-
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({
|
|
948
1029
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
949
1030
|
});
|
|
950
1031
|
class Model {
|
|
@@ -955,82 +1036,7 @@ class Model {
|
|
|
955
1036
|
on(arg1, arg2, arg3) {
|
|
956
1037
|
if (typeof arg1 == "function")
|
|
957
1038
|
return createEffect(this.is, arg1, arg2);
|
|
958
|
-
|
|
959
|
-
const keys = typeof arg1 == "string" ? [arg1] :
|
|
960
|
-
typeof arg1 == "object" ? arg1 :
|
|
961
|
-
undefined;
|
|
962
|
-
if (typeof arg2 == "function" && keys)
|
|
963
|
-
return Control.for(this, control => {
|
|
964
|
-
for (const key of keys)
|
|
965
|
-
try {
|
|
966
|
-
void this[key];
|
|
967
|
-
}
|
|
968
|
-
catch (e) { }
|
|
969
|
-
const invoke = single
|
|
970
|
-
? () => arg2.call(this, control.state.get(arg1), arg1)
|
|
971
|
-
: (frame) => arg2.call(this, frame);
|
|
972
|
-
const removeListener = control.addListener(key => {
|
|
973
|
-
if (!key && !keys.length)
|
|
974
|
-
invoke([]);
|
|
975
|
-
if (keys.includes(key)) {
|
|
976
|
-
if (arg3)
|
|
977
|
-
removeListener();
|
|
978
|
-
return invoke;
|
|
979
|
-
}
|
|
980
|
-
});
|
|
981
|
-
return removeListener;
|
|
982
|
-
});
|
|
983
|
-
return new Promise((resolve, reject) => {
|
|
984
|
-
const timeout = (message) => {
|
|
985
|
-
const k = keys ? keys.join(", ") : "any";
|
|
986
|
-
removeListener();
|
|
987
|
-
reject(Oops$5.Timeout(k, message));
|
|
988
|
-
};
|
|
989
|
-
const removeListener = Control.for(this, control => {
|
|
990
|
-
const pending = control.frame;
|
|
991
|
-
if (keys === null) {
|
|
992
|
-
if (pending.size)
|
|
993
|
-
reject(Oops$5.StrictNoUpdate());
|
|
994
|
-
else
|
|
995
|
-
resolve(null);
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
if (keys) {
|
|
999
|
-
if (keys.length) {
|
|
1000
|
-
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
1001
|
-
reject(Oops$5.KeysExpected(keys[0]));
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
else
|
|
1005
|
-
for (const key of keys)
|
|
1006
|
-
try {
|
|
1007
|
-
void this[key];
|
|
1008
|
-
}
|
|
1009
|
-
catch (e) { }
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
1013
|
-
reject(Oops$5.StrictUpdate());
|
|
1014
|
-
return;
|
|
1015
|
-
}
|
|
1016
|
-
else
|
|
1017
|
-
control.waiting.add(resolve);
|
|
1018
|
-
return control.addListener(key => {
|
|
1019
|
-
if (!key) {
|
|
1020
|
-
if (keys && !keys.length)
|
|
1021
|
-
resolve([]);
|
|
1022
|
-
else
|
|
1023
|
-
timeout(`lifetime of ${this}`);
|
|
1024
|
-
}
|
|
1025
|
-
else if (!keys || keys.includes(key)) {
|
|
1026
|
-
removeListener();
|
|
1027
|
-
return keys => resolve(single ? control.state.get(key) : keys);
|
|
1028
|
-
}
|
|
1029
|
-
});
|
|
1030
|
-
});
|
|
1031
|
-
if (arg2 && typeof arg2 == "number")
|
|
1032
|
-
setTimeout(() => timeout(`${arg2}ms`), arg2);
|
|
1033
|
-
});
|
|
1039
|
+
return addEventListener(this.is, arg1, arg2, arg3);
|
|
1034
1040
|
}
|
|
1035
1041
|
export(subset) {
|
|
1036
1042
|
const { state } = Control.for(this);
|
|
@@ -1283,6 +1289,19 @@ function useValue(source, compute, suspend) {
|
|
|
1283
1289
|
else
|
|
1284
1290
|
refresh();
|
|
1285
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
|
+
}
|
|
1286
1305
|
if (value instanceof Promise) {
|
|
1287
1306
|
value.then(set);
|
|
1288
1307
|
value = undefined;
|