@expressive/mvc 1.0.0-beta.25 → 1.0.0-beta.29
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.esm.js +356 -334
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +356 -334
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/types/model.d.ts +38 -14
- package/types/types.d.ts +1 -1
package/lib/index.js
CHANGED
|
@@ -24,7 +24,7 @@ function issues(register) {
|
|
|
24
24
|
return Library;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const Oops$
|
|
27
|
+
const Oops$8 = issues({
|
|
28
28
|
BadEffectCallback: () => `Callback for effect-callback may only return a function.`
|
|
29
29
|
});
|
|
30
30
|
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys: keys$1, values } = Object;
|
|
@@ -53,7 +53,7 @@ function createEffect(callback) {
|
|
|
53
53
|
if (unSet instanceof Promise)
|
|
54
54
|
unSet = undefined;
|
|
55
55
|
if (unSet && typeof unSet !== "function")
|
|
56
|
-
throw Oops$
|
|
56
|
+
throw Oops$8.BadEffectCallback();
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
function createValueEffect(callback) {
|
|
@@ -69,7 +69,7 @@ function createValueEffect(callback) {
|
|
|
69
69
|
if (typeof out == "function")
|
|
70
70
|
unSet = out;
|
|
71
71
|
else
|
|
72
|
-
throw Oops$
|
|
72
|
+
throw Oops$8.BadEffectCallback();
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
function select(source, select) {
|
|
@@ -96,14 +96,34 @@ class Subscriber {
|
|
|
96
96
|
constructor(parent, onUpdate) {
|
|
97
97
|
this.onUpdate = onUpdate;
|
|
98
98
|
this.active = false;
|
|
99
|
-
this.
|
|
99
|
+
this.handle = {};
|
|
100
100
|
this.dependant = new Set();
|
|
101
|
+
this.debug = () => {
|
|
102
|
+
const update = [];
|
|
103
|
+
this.notify = keys => {
|
|
104
|
+
update.splice(0, update.length, ...keys.filter(k => k in this.handle));
|
|
105
|
+
};
|
|
106
|
+
return update;
|
|
107
|
+
};
|
|
108
|
+
this.listen = (key, from) => {
|
|
109
|
+
const handler = this.handle[key];
|
|
110
|
+
if (!handler)
|
|
111
|
+
return;
|
|
112
|
+
if (typeof handler == "function")
|
|
113
|
+
handler();
|
|
114
|
+
const notify = this.onUpdate(key, from);
|
|
115
|
+
if (notify)
|
|
116
|
+
from.waiting.add(notify);
|
|
117
|
+
if (this.notify)
|
|
118
|
+
from.waiting.add(this.notify);
|
|
119
|
+
};
|
|
101
120
|
if (!(parent instanceof Controller))
|
|
102
121
|
parent = manage(parent);
|
|
103
122
|
this.parent = parent;
|
|
104
123
|
this.source = parent.subject;
|
|
105
124
|
this.proxy = create(parent.subject);
|
|
106
125
|
define(this.proxy, LOCAL, this);
|
|
126
|
+
defineLazy(this.proxy, UPDATE, this.debug);
|
|
107
127
|
for (const key in parent.state)
|
|
108
128
|
this.spy(key);
|
|
109
129
|
}
|
|
@@ -123,43 +143,47 @@ class Subscriber {
|
|
|
123
143
|
enumerable: true
|
|
124
144
|
});
|
|
125
145
|
}
|
|
126
|
-
follow(key,
|
|
127
|
-
this.
|
|
146
|
+
follow(key, callback) {
|
|
147
|
+
this.handle[key] = callback || true;
|
|
128
148
|
}
|
|
129
149
|
commit() {
|
|
130
|
-
const
|
|
131
|
-
const onDone = parent.addListener(follows);
|
|
150
|
+
const onDone = this.parent.addListener(this.listen);
|
|
132
151
|
this.active = true;
|
|
133
|
-
dependant.forEach(x => x.commit());
|
|
152
|
+
this.dependant.forEach(x => x.commit());
|
|
134
153
|
return this.release = () => {
|
|
135
|
-
dependant.forEach(x => x.release());
|
|
154
|
+
this.dependant.forEach(x => x.release());
|
|
136
155
|
onDone();
|
|
137
156
|
};
|
|
138
157
|
}
|
|
139
158
|
}
|
|
140
159
|
|
|
141
|
-
const Oops$
|
|
160
|
+
const Oops$7 = issues({
|
|
142
161
|
ComputeFailed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
|
|
143
162
|
ComputedEarly: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
|
|
144
163
|
});
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
const
|
|
148
|
-
const
|
|
164
|
+
const INIT = new WeakSet();
|
|
165
|
+
const INFO = new WeakMap();
|
|
166
|
+
const USED = new WeakMap();
|
|
167
|
+
const KEYS = new WeakMap();
|
|
149
168
|
function prepare(parent, key, source, setter, getter) {
|
|
150
169
|
let sub;
|
|
151
170
|
const { state, subject } = parent;
|
|
152
171
|
const info = { key, parent, priority: 1 };
|
|
172
|
+
let register = USED.get(parent);
|
|
173
|
+
if (!register) {
|
|
174
|
+
register = new Map();
|
|
175
|
+
USED.set(parent, register);
|
|
176
|
+
}
|
|
177
|
+
register.set(key, info);
|
|
153
178
|
const current = getter
|
|
154
179
|
? () => getter.call(subject, state[key], key)
|
|
155
180
|
: () => state[key];
|
|
156
|
-
const prioritize = register(parent, key, info);
|
|
157
181
|
function compute(initial) {
|
|
158
182
|
try {
|
|
159
183
|
return setter.call(sub.proxy, sub.proxy);
|
|
160
184
|
}
|
|
161
185
|
catch (err) {
|
|
162
|
-
Oops$
|
|
186
|
+
Oops$7.ComputeFailed(subject, key, !!initial).warn();
|
|
163
187
|
throw err;
|
|
164
188
|
}
|
|
165
189
|
}
|
|
@@ -178,8 +202,19 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
178
202
|
}
|
|
179
203
|
}
|
|
180
204
|
}
|
|
205
|
+
function defer(_key, from) {
|
|
206
|
+
let pending = KEYS.get(from);
|
|
207
|
+
if (!pending)
|
|
208
|
+
KEYS.set(from, pending = []);
|
|
209
|
+
if (info.parent !== from)
|
|
210
|
+
update();
|
|
211
|
+
else {
|
|
212
|
+
const after = pending.findIndex(peer => (info.priority > INFO.get(peer).priority));
|
|
213
|
+
pending.splice(after + 1, 0, update);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
181
216
|
function create(early) {
|
|
182
|
-
sub = new Subscriber(source(),
|
|
217
|
+
sub = new Subscriber(source(), defer);
|
|
183
218
|
defineProperty(state, key, {
|
|
184
219
|
value: undefined,
|
|
185
220
|
writable: true
|
|
@@ -194,21 +229,24 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
194
229
|
}
|
|
195
230
|
catch (e) {
|
|
196
231
|
if (early)
|
|
197
|
-
Oops$
|
|
232
|
+
Oops$7.ComputedEarly(key).warn();
|
|
198
233
|
throw e;
|
|
199
234
|
}
|
|
200
235
|
finally {
|
|
201
236
|
sub.commit();
|
|
202
|
-
for (const key in sub.
|
|
203
|
-
|
|
237
|
+
for (const key in sub.handle) {
|
|
238
|
+
const peer = register.get(key);
|
|
239
|
+
if (peer && peer.priority >= info.priority)
|
|
240
|
+
info.priority = peer.priority + 1;
|
|
241
|
+
}
|
|
204
242
|
}
|
|
205
243
|
return current();
|
|
206
244
|
}
|
|
207
245
|
setAlias(update, `try ${key}`);
|
|
208
246
|
setAlias(create, `new ${key}`);
|
|
209
247
|
setAlias(setter, `run ${key}`);
|
|
210
|
-
|
|
211
|
-
|
|
248
|
+
INIT.add(create);
|
|
249
|
+
INFO.set(update, info);
|
|
212
250
|
for (const on of [state, subject])
|
|
213
251
|
defineProperty(on, key, {
|
|
214
252
|
get: create,
|
|
@@ -216,53 +254,27 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
216
254
|
enumerable: true
|
|
217
255
|
});
|
|
218
256
|
}
|
|
219
|
-
function register(on, key, info) {
|
|
220
|
-
let register = ComputedUsed.get(on);
|
|
221
|
-
if (!register)
|
|
222
|
-
ComputedUsed.set(on, register = new Map());
|
|
223
|
-
register.set(key, info);
|
|
224
|
-
return (key) => {
|
|
225
|
-
const peer = register.get(key);
|
|
226
|
-
if (peer && peer.priority >= info.priority)
|
|
227
|
-
info.priority = peer.priority + 1;
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
257
|
function ensure(on, keys) {
|
|
231
258
|
for (const key of keys) {
|
|
232
259
|
const desc = getOwnPropertyDescriptor(on.subject, key);
|
|
233
260
|
const getter = desc && desc.get;
|
|
234
|
-
if (
|
|
261
|
+
if (INIT.has(getter))
|
|
235
262
|
getter(true);
|
|
236
263
|
}
|
|
237
264
|
}
|
|
238
|
-
function capture(on, request) {
|
|
239
|
-
const compute = ComputedInfo.get(request);
|
|
240
|
-
const callback = request;
|
|
241
|
-
if (!compute)
|
|
242
|
-
return;
|
|
243
|
-
let pending = ComputedKeys.get(on);
|
|
244
|
-
if (!pending)
|
|
245
|
-
ComputedKeys.set(on, pending = []);
|
|
246
|
-
if (compute.parent !== on)
|
|
247
|
-
callback();
|
|
248
|
-
else {
|
|
249
|
-
const queue = pending.findIndex(peer => compute.priority > ComputedInfo.get(peer).priority);
|
|
250
|
-
pending.splice(queue + 1, 0, callback);
|
|
251
|
-
}
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
265
|
function flush(on) {
|
|
255
266
|
const handled = on.frame;
|
|
256
|
-
|
|
257
|
-
if (pending)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
267
|
+
const pending = KEYS.get(on);
|
|
268
|
+
if (!pending)
|
|
269
|
+
return;
|
|
270
|
+
while (pending.length) {
|
|
271
|
+
const why = [...handled];
|
|
272
|
+
const compute = pending.shift();
|
|
273
|
+
const { key } = INFO.get(compute);
|
|
274
|
+
if (!handled.has(key))
|
|
275
|
+
compute(why);
|
|
276
|
+
}
|
|
277
|
+
KEYS.delete(on);
|
|
266
278
|
}
|
|
267
279
|
|
|
268
280
|
const Lifecycle = {
|
|
@@ -313,6 +325,7 @@ function eventsFor(prefix) {
|
|
|
313
325
|
}
|
|
314
326
|
|
|
315
327
|
const CONTROL = Symbol("control");
|
|
328
|
+
const UPDATE = Symbol("update");
|
|
316
329
|
const LOCAL = Symbol("local");
|
|
317
330
|
const STATE = Symbol("state");
|
|
318
331
|
function manage(src) {
|
|
@@ -341,8 +354,8 @@ class Controller {
|
|
|
341
354
|
this.subject = subject;
|
|
342
355
|
this.state = {};
|
|
343
356
|
this.frame = new Set();
|
|
344
|
-
this.
|
|
345
|
-
this.
|
|
357
|
+
this.waiting = new Set();
|
|
358
|
+
this.followers = new Set();
|
|
346
359
|
}
|
|
347
360
|
static setup(onto) {
|
|
348
361
|
const control = new this(onto);
|
|
@@ -408,18 +421,12 @@ class Controller {
|
|
|
408
421
|
this.update(key, value);
|
|
409
422
|
};
|
|
410
423
|
}
|
|
411
|
-
addListener(
|
|
412
|
-
this.
|
|
424
|
+
addListener(listener) {
|
|
425
|
+
this.followers.add(listener);
|
|
413
426
|
return () => {
|
|
414
|
-
this.
|
|
427
|
+
this.followers.delete(listener);
|
|
415
428
|
};
|
|
416
429
|
}
|
|
417
|
-
include(to) {
|
|
418
|
-
if (capture(this, to))
|
|
419
|
-
return;
|
|
420
|
-
else
|
|
421
|
-
this.waiting.push(to);
|
|
422
|
-
}
|
|
423
430
|
update(key, value) {
|
|
424
431
|
if (1 in arguments)
|
|
425
432
|
this.state[key] = value;
|
|
@@ -428,15 +435,22 @@ class Controller {
|
|
|
428
435
|
if (!this.frame.size)
|
|
429
436
|
setTimeout(() => this.emit(), 0);
|
|
430
437
|
this.frame.add(key);
|
|
431
|
-
for (const subscription of this.
|
|
432
|
-
|
|
433
|
-
|
|
438
|
+
for (const subscription of this.followers) {
|
|
439
|
+
const notify = subscription(key, this);
|
|
440
|
+
if (notify)
|
|
441
|
+
this.waiting.add(notify);
|
|
442
|
+
}
|
|
434
443
|
}
|
|
435
444
|
emit() {
|
|
436
445
|
flush(this);
|
|
437
|
-
const keys =
|
|
438
|
-
const handle = new Set(this.waiting
|
|
446
|
+
const keys = Object.freeze([...this.frame]);
|
|
447
|
+
const handle = new Set(this.waiting);
|
|
448
|
+
this.waiting.clear();
|
|
439
449
|
this.frame.clear();
|
|
450
|
+
defineProperty(this.subject, UPDATE, {
|
|
451
|
+
configurable: true,
|
|
452
|
+
value: keys
|
|
453
|
+
});
|
|
440
454
|
handle.forEach(callback => {
|
|
441
455
|
try {
|
|
442
456
|
callback(keys);
|
|
@@ -448,104 +462,52 @@ class Controller {
|
|
|
448
462
|
function keys(from, using) {
|
|
449
463
|
if (typeof using == "string")
|
|
450
464
|
return [using];
|
|
451
|
-
if (typeof using == "object")
|
|
452
|
-
|
|
465
|
+
if (typeof using == "object") {
|
|
466
|
+
using = Array.from(using);
|
|
467
|
+
if (using.length === 0)
|
|
468
|
+
using = undefined;
|
|
469
|
+
else
|
|
470
|
+
return using;
|
|
471
|
+
}
|
|
453
472
|
return from.select(using);
|
|
454
473
|
}
|
|
455
474
|
|
|
456
|
-
function child(
|
|
475
|
+
function child(source, name) {
|
|
457
476
|
return apply(function child(key) {
|
|
458
|
-
const
|
|
459
|
-
const
|
|
477
|
+
const context = new WeakMap();
|
|
478
|
+
const current = source.call(this, key);
|
|
460
479
|
function subscribe(sub) {
|
|
461
480
|
let child;
|
|
462
481
|
function start() {
|
|
463
|
-
const instance =
|
|
482
|
+
const instance = current();
|
|
464
483
|
if (instance) {
|
|
465
484
|
child = new Subscriber(instance, sub.onUpdate);
|
|
466
485
|
if (sub.active)
|
|
467
486
|
child.commit();
|
|
468
487
|
sub.dependant.add(child);
|
|
469
|
-
|
|
488
|
+
context.set(sub, child.proxy);
|
|
470
489
|
}
|
|
471
490
|
}
|
|
472
|
-
function
|
|
491
|
+
function restart() {
|
|
473
492
|
if (child) {
|
|
474
493
|
child.release();
|
|
475
494
|
sub.dependant.delete(child);
|
|
476
|
-
|
|
495
|
+
context.set(sub, undefined);
|
|
477
496
|
child = undefined;
|
|
478
497
|
}
|
|
479
498
|
start();
|
|
480
|
-
sub.onUpdate();
|
|
481
499
|
}
|
|
482
500
|
start();
|
|
483
|
-
sub.follow(key,
|
|
501
|
+
sub.follow(key, restart);
|
|
484
502
|
}
|
|
485
503
|
return (local) => {
|
|
486
504
|
if (!local)
|
|
487
|
-
return
|
|
488
|
-
if (!
|
|
505
|
+
return current();
|
|
506
|
+
if (!context.has(local))
|
|
489
507
|
subscribe(local);
|
|
490
|
-
return
|
|
508
|
+
return context.get(local);
|
|
491
509
|
};
|
|
492
|
-
}, name ||
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
const Oops$7 = issues({
|
|
496
|
-
HasPropertyUndefined: (control, property) => `${control}.${property} is marked as required for this render.`
|
|
497
|
-
});
|
|
498
|
-
function use$1(init) {
|
|
499
|
-
const [state, update] = react.useState(() => [
|
|
500
|
-
init(() => update(state.concat()))
|
|
501
|
-
]);
|
|
502
|
-
return state[0];
|
|
503
|
-
}
|
|
504
|
-
function useLazy(Type, callback) {
|
|
505
|
-
const instance = react.useMemo(() => {
|
|
506
|
-
const instance = Type.create();
|
|
507
|
-
if (callback)
|
|
508
|
-
callback(instance);
|
|
509
|
-
return instance;
|
|
510
|
-
}, []);
|
|
511
|
-
react.useLayoutEffect(() => () => instance.destroy(), []);
|
|
512
|
-
return instance;
|
|
513
|
-
}
|
|
514
|
-
function useWatcher(target, focus, expected) {
|
|
515
|
-
const hook = use$1(refresh => {
|
|
516
|
-
const sub = new Subscriber(target, refresh);
|
|
517
|
-
if (focus) {
|
|
518
|
-
const src = sub.proxy;
|
|
519
|
-
const key = keys(sub.parent, focus)[0];
|
|
520
|
-
defineProperty(sub, "proxy", {
|
|
521
|
-
get() {
|
|
522
|
-
if (src[key] === undefined && expected)
|
|
523
|
-
throw Oops$7.HasPropertyUndefined(target, key);
|
|
524
|
-
return src[key];
|
|
525
|
-
}
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
return sub;
|
|
529
|
-
});
|
|
530
|
-
react.useLayoutEffect(() => hook.commit(), []);
|
|
531
|
-
return hook.proxy;
|
|
532
|
-
}
|
|
533
|
-
function useModel(Type, callback) {
|
|
534
|
-
const hook = use$1(refresh => {
|
|
535
|
-
const instance = new Type();
|
|
536
|
-
const control = manage(instance);
|
|
537
|
-
const sub = new Subscriber(control, refresh);
|
|
538
|
-
const release = control.addListener({
|
|
539
|
-
[Lifecycle.WILL_UNMOUNT]() {
|
|
540
|
-
instance.destroy();
|
|
541
|
-
release();
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
if (callback)
|
|
545
|
-
callback(instance);
|
|
546
|
-
return sub;
|
|
547
|
-
});
|
|
548
|
-
return hook.proxy;
|
|
510
|
+
}, name || source.name);
|
|
549
511
|
}
|
|
550
512
|
|
|
551
513
|
const Oops$6 = issues({
|
|
@@ -598,6 +560,219 @@ function getPending(subject) {
|
|
|
598
560
|
return pending;
|
|
599
561
|
}
|
|
600
562
|
|
|
563
|
+
const Oops$5 = issues({
|
|
564
|
+
DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
|
|
565
|
+
BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
566
|
+
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
|
|
567
|
+
});
|
|
568
|
+
function createRef(key, cb) {
|
|
569
|
+
const refObjectFunction = this.setter(key, cb && createValueEffect(cb));
|
|
570
|
+
defineProperty(refObjectFunction, "current", {
|
|
571
|
+
set: refObjectFunction,
|
|
572
|
+
get: () => this.state[key]
|
|
573
|
+
});
|
|
574
|
+
return refObjectFunction;
|
|
575
|
+
}
|
|
576
|
+
function ref(arg) {
|
|
577
|
+
return apply(function ref(key) {
|
|
578
|
+
let value = {};
|
|
579
|
+
if (typeof arg == "object") {
|
|
580
|
+
const source = manage(arg);
|
|
581
|
+
for (const key in source.state)
|
|
582
|
+
defineLazy(value, key, createRef.bind(source, key));
|
|
583
|
+
}
|
|
584
|
+
else
|
|
585
|
+
value = createRef.call(this, key, arg);
|
|
586
|
+
return { value };
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
function act(task) {
|
|
590
|
+
return apply(function act(key) {
|
|
591
|
+
let pending = false;
|
|
592
|
+
const invoke = (...args) => {
|
|
593
|
+
if (pending)
|
|
594
|
+
return Promise.reject(Oops$5.DuplicateAction(key));
|
|
595
|
+
pending = true;
|
|
596
|
+
this.update(key);
|
|
597
|
+
return new Promise(res => {
|
|
598
|
+
res(task.apply(this.subject, args));
|
|
599
|
+
}).finally(() => {
|
|
600
|
+
pending = false;
|
|
601
|
+
this.update(key);
|
|
602
|
+
});
|
|
603
|
+
};
|
|
604
|
+
setAlias(invoke, `run ${key}`);
|
|
605
|
+
defineProperty(invoke, "active", {
|
|
606
|
+
get: () => pending
|
|
607
|
+
});
|
|
608
|
+
return {
|
|
609
|
+
value: invoke,
|
|
610
|
+
writable: false
|
|
611
|
+
};
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
function from(source, setter, getter) {
|
|
615
|
+
return apply(function from(key) {
|
|
616
|
+
const { subject } = this;
|
|
617
|
+
let getSource;
|
|
618
|
+
// Easy mistake, using a peer, will always be unresolved.
|
|
619
|
+
if (typeof source == "symbol")
|
|
620
|
+
throw Oops$5.PeerNotAllowed(subject, key);
|
|
621
|
+
// replace source controller in-case different
|
|
622
|
+
if (typeof source == "object")
|
|
623
|
+
getSource = () => manage(source);
|
|
624
|
+
// specifically an arrow function (getter factory)
|
|
625
|
+
else if (!source.prototype) {
|
|
626
|
+
setter = source.call(subject, key);
|
|
627
|
+
getSource = () => this;
|
|
628
|
+
}
|
|
629
|
+
// is a peer Model (constructor)
|
|
630
|
+
else if (Model.isTypeof(source))
|
|
631
|
+
getSource = pendingAccess(subject, source, key, true);
|
|
632
|
+
// Regular function is to ambiguous so not allowed.
|
|
633
|
+
else
|
|
634
|
+
throw Oops$5.BadComputedSource(subject, key, source);
|
|
635
|
+
prepare(this, key, getSource, setter, getter);
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const Oops$4 = issues({
|
|
640
|
+
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
641
|
+
});
|
|
642
|
+
function pending(source, compute) {
|
|
643
|
+
return (source === undefined ?
|
|
644
|
+
suspendForValue() :
|
|
645
|
+
typeof source == "function" && !source.prototype ?
|
|
646
|
+
suspendForAsync(source) :
|
|
647
|
+
suspendForComputed(source, compute));
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Get value, suspend instead if undefined.
|
|
651
|
+
*
|
|
652
|
+
* Throws suspense promise also interpretable as an error.
|
|
653
|
+
* React could handle it but other contexts probably not.
|
|
654
|
+
*/
|
|
655
|
+
function pendingValue(via, key) {
|
|
656
|
+
const value = via.state[key];
|
|
657
|
+
if (value === undefined)
|
|
658
|
+
throw suspend(via, key);
|
|
659
|
+
return value;
|
|
660
|
+
}
|
|
661
|
+
function suspend(source, key) {
|
|
662
|
+
const error = Oops$4.ValueNotReady(source.subject, key);
|
|
663
|
+
const promise = new Promise(resolve => {
|
|
664
|
+
const release = source.addListener(forKey => {
|
|
665
|
+
if (forKey == key)
|
|
666
|
+
return () => {
|
|
667
|
+
if (source.state[key] !== undefined) {
|
|
668
|
+
release();
|
|
669
|
+
resolve();
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
return Object.assign(promise, {
|
|
675
|
+
toString: () => String(error),
|
|
676
|
+
name: "Suspense",
|
|
677
|
+
message: error.message,
|
|
678
|
+
stack: error.stack
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
function suspendForComputed(source, compute) {
|
|
682
|
+
function getter(_value, key) {
|
|
683
|
+
return pendingValue(manage(this), key);
|
|
684
|
+
}
|
|
685
|
+
return from(source, compute, getter);
|
|
686
|
+
}
|
|
687
|
+
function suspendForValue() {
|
|
688
|
+
return apply(function pending(key) {
|
|
689
|
+
this.state[key] = undefined;
|
|
690
|
+
return {
|
|
691
|
+
set: this.setter(key),
|
|
692
|
+
get: () => pendingValue(this, key)
|
|
693
|
+
};
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
function suspendForAsync(source) {
|
|
697
|
+
return apply(function suspense(key) {
|
|
698
|
+
const subject = this.subject;
|
|
699
|
+
let waiting = true;
|
|
700
|
+
let value;
|
|
701
|
+
let error;
|
|
702
|
+
return () => {
|
|
703
|
+
if (error)
|
|
704
|
+
throw error;
|
|
705
|
+
if (!waiting)
|
|
706
|
+
return value;
|
|
707
|
+
const issue = Oops$4.ValueNotReady(subject, key);
|
|
708
|
+
let suspend = source
|
|
709
|
+
.call(subject, key)
|
|
710
|
+
.catch(err => error = err)
|
|
711
|
+
.then(out => value = out)
|
|
712
|
+
.finally(() => waiting = false);
|
|
713
|
+
throw Object.assign(suspend, {
|
|
714
|
+
message: issue.message,
|
|
715
|
+
stack: issue.stack
|
|
716
|
+
});
|
|
717
|
+
};
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function use$1(init) {
|
|
722
|
+
const [state, update] = react.useState(() => [
|
|
723
|
+
init(() => update(state.concat()))
|
|
724
|
+
]);
|
|
725
|
+
return state[0];
|
|
726
|
+
}
|
|
727
|
+
function useLazy(Type, callback) {
|
|
728
|
+
const instance = react.useMemo(() => {
|
|
729
|
+
const instance = Type.create();
|
|
730
|
+
if (callback)
|
|
731
|
+
callback(instance);
|
|
732
|
+
return instance;
|
|
733
|
+
}, []);
|
|
734
|
+
react.useLayoutEffect(() => () => instance.destroy(), []);
|
|
735
|
+
return instance;
|
|
736
|
+
}
|
|
737
|
+
function useWatcher(target, focus, expected) {
|
|
738
|
+
const hook = use$1(refresh => {
|
|
739
|
+
const sub = new Subscriber(target, () => refresh);
|
|
740
|
+
if (focus) {
|
|
741
|
+
const source = sub.proxy;
|
|
742
|
+
const key = keys(sub.parent, focus)[0];
|
|
743
|
+
defineProperty(sub, "proxy", {
|
|
744
|
+
get() {
|
|
745
|
+
const value = source[key];
|
|
746
|
+
if (value === undefined && expected)
|
|
747
|
+
throw suspend(sub.parent, key);
|
|
748
|
+
return value;
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
return sub;
|
|
753
|
+
});
|
|
754
|
+
react.useLayoutEffect(() => hook.commit(), []);
|
|
755
|
+
return hook.proxy;
|
|
756
|
+
}
|
|
757
|
+
function useModel(Type, callback) {
|
|
758
|
+
const hook = use$1(refresh => {
|
|
759
|
+
const instance = new Type();
|
|
760
|
+
const control = manage(instance);
|
|
761
|
+
const sub = new Subscriber(control, () => refresh);
|
|
762
|
+
const release = control.addListener((key) => {
|
|
763
|
+
if (key == Lifecycle.WILL_UNMOUNT)
|
|
764
|
+
return () => {
|
|
765
|
+
instance.destroy();
|
|
766
|
+
release();
|
|
767
|
+
};
|
|
768
|
+
});
|
|
769
|
+
if (callback)
|
|
770
|
+
callback(instance);
|
|
771
|
+
return sub;
|
|
772
|
+
});
|
|
773
|
+
return hook.proxy;
|
|
774
|
+
}
|
|
775
|
+
|
|
601
776
|
class Lookup {
|
|
602
777
|
constructor() {
|
|
603
778
|
this.table = new Map();
|
|
@@ -653,7 +828,7 @@ class Lookup {
|
|
|
653
828
|
}
|
|
654
829
|
}
|
|
655
830
|
|
|
656
|
-
const Oops$
|
|
831
|
+
const Oops$3 = issues({
|
|
657
832
|
NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
|
|
658
833
|
NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
|
|
659
834
|
BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
|
|
@@ -663,7 +838,7 @@ const useLookup = () => react.useContext(LookupContext);
|
|
|
663
838
|
function useFromContext(Type, strict) {
|
|
664
839
|
const instance = useLookup().get(Type);
|
|
665
840
|
if (!instance && strict)
|
|
666
|
-
throw Oops$
|
|
841
|
+
throw Oops$3.NothingInContext(Type.name);
|
|
667
842
|
return instance;
|
|
668
843
|
}
|
|
669
844
|
function Consumer(props) {
|
|
@@ -674,13 +849,13 @@ function Consumer(props) {
|
|
|
674
849
|
if (typeof callback == "function")
|
|
675
850
|
callback(Control.get(!!has));
|
|
676
851
|
else
|
|
677
|
-
throw Oops$
|
|
852
|
+
throw Oops$3.BadConsumerProps();
|
|
678
853
|
return null;
|
|
679
854
|
}
|
|
680
855
|
function useNewContext(from, inject) {
|
|
681
856
|
return react.useMemo(() => {
|
|
682
857
|
if (!inject)
|
|
683
|
-
throw Oops$
|
|
858
|
+
throw Oops$3.NoProviderType();
|
|
684
859
|
const context = from.push(inject);
|
|
685
860
|
for (const instance of context.local)
|
|
686
861
|
for (const apply of getPending(instance))
|
|
@@ -705,7 +880,7 @@ function RenderFunction(props) {
|
|
|
705
880
|
const hook = use$1(refresh => {
|
|
706
881
|
const targets = props.context.local;
|
|
707
882
|
if (targets.length == 1)
|
|
708
|
-
return new Subscriber(targets[0], refresh);
|
|
883
|
+
return new Subscriber(targets[0], () => refresh);
|
|
709
884
|
return {};
|
|
710
885
|
});
|
|
711
886
|
if (hook.commit)
|
|
@@ -723,7 +898,7 @@ function Provider(props) {
|
|
|
723
898
|
: render);
|
|
724
899
|
}
|
|
725
900
|
|
|
726
|
-
const Oops$
|
|
901
|
+
const Oops$2 = issues({
|
|
727
902
|
StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
|
|
728
903
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
729
904
|
});
|
|
@@ -736,7 +911,7 @@ class Model {
|
|
|
736
911
|
define(this, "set", this);
|
|
737
912
|
defer(control, "on");
|
|
738
913
|
defer(control, "effect");
|
|
739
|
-
control.
|
|
914
|
+
control.waiting.add(() => {
|
|
740
915
|
delete this.on;
|
|
741
916
|
delete this.effect;
|
|
742
917
|
});
|
|
@@ -748,7 +923,7 @@ class Model {
|
|
|
748
923
|
}
|
|
749
924
|
tag(id) {
|
|
750
925
|
const hook = use$1(refresh => {
|
|
751
|
-
return new Subscriber(this, refresh);
|
|
926
|
+
return new Subscriber(this, () => refresh);
|
|
752
927
|
});
|
|
753
928
|
useElementLifecycle(hook, id || 0);
|
|
754
929
|
return hook.proxy;
|
|
@@ -757,29 +932,27 @@ class Model {
|
|
|
757
932
|
const hook = use$1(refresh => {
|
|
758
933
|
if (callback)
|
|
759
934
|
callback(this);
|
|
760
|
-
return new Subscriber(this, refresh);
|
|
935
|
+
return new Subscriber(this, () => refresh);
|
|
761
936
|
});
|
|
762
937
|
useComponentLifecycle(hook);
|
|
763
938
|
return hook.proxy;
|
|
764
939
|
}
|
|
765
940
|
on(subset, handler, squash, once) {
|
|
766
941
|
const control = manage(this);
|
|
767
|
-
const
|
|
768
|
-
const batch = {};
|
|
769
|
-
const remove = control.addListener(batch);
|
|
942
|
+
const request = keys(control, subset);
|
|
770
943
|
const callback = squash
|
|
771
944
|
? handler.bind(this)
|
|
772
|
-
:
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
const handle = once
|
|
778
|
-
? (k) => { remove(); callback(k); }
|
|
945
|
+
: frame => frame
|
|
946
|
+
.filter(k => request.includes(k))
|
|
947
|
+
.forEach(k => handler.call(this, control.state[k], k));
|
|
948
|
+
const trigger = once
|
|
949
|
+
? frame => { remove(); callback(frame); }
|
|
779
950
|
: callback;
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
951
|
+
ensure(control, request);
|
|
952
|
+
const remove = control.addListener(key => {
|
|
953
|
+
if (request.includes(key))
|
|
954
|
+
return trigger;
|
|
955
|
+
});
|
|
783
956
|
return remove;
|
|
784
957
|
}
|
|
785
958
|
once(select, callback, squash) {
|
|
@@ -800,7 +973,7 @@ class Model {
|
|
|
800
973
|
return this.on(select, invoke, true);
|
|
801
974
|
}
|
|
802
975
|
else {
|
|
803
|
-
const sub = new Subscriber(control, invoke);
|
|
976
|
+
const sub = new Subscriber(control, () => invoke);
|
|
804
977
|
target = sub.proxy;
|
|
805
978
|
invoke();
|
|
806
979
|
return sub.commit();
|
|
@@ -824,7 +997,7 @@ class Model {
|
|
|
824
997
|
arg = select(this, arg);
|
|
825
998
|
if (typeof arg == "boolean") {
|
|
826
999
|
if (!control.pending === arg)
|
|
827
|
-
return Promise.reject(Oops$
|
|
1000
|
+
return Promise.reject(Oops$2.StrictUpdate(arg));
|
|
828
1001
|
}
|
|
829
1002
|
else if (arg) {
|
|
830
1003
|
control.update(arg);
|
|
@@ -841,11 +1014,11 @@ class Model {
|
|
|
841
1014
|
then(callback) {
|
|
842
1015
|
if (callback)
|
|
843
1016
|
if (control.pending)
|
|
844
|
-
control.
|
|
1017
|
+
control.waiting.add(callback);
|
|
845
1018
|
else
|
|
846
1019
|
callback(false);
|
|
847
1020
|
else
|
|
848
|
-
throw Oops$
|
|
1021
|
+
throw Oops$2.NoChaining();
|
|
849
1022
|
}
|
|
850
1023
|
};
|
|
851
1024
|
}
|
|
@@ -909,6 +1082,7 @@ class Model {
|
|
|
909
1082
|
Model.CONTROL = CONTROL;
|
|
910
1083
|
Model.STATE = STATE;
|
|
911
1084
|
Model.LOCAL = LOCAL;
|
|
1085
|
+
Model.WHY = UPDATE;
|
|
912
1086
|
defineLazy(Model, CONTROL, function () {
|
|
913
1087
|
return new Controller(this).start();
|
|
914
1088
|
});
|
|
@@ -917,7 +1091,7 @@ function defer(on, method) {
|
|
|
917
1091
|
const real = subject[method];
|
|
918
1092
|
subject[method] = (...args) => {
|
|
919
1093
|
let done;
|
|
920
|
-
waiting.
|
|
1094
|
+
waiting.add(() => {
|
|
921
1095
|
done = real.apply(subject, args);
|
|
922
1096
|
});
|
|
923
1097
|
return () => done();
|
|
@@ -925,7 +1099,7 @@ function defer(on, method) {
|
|
|
925
1099
|
}
|
|
926
1100
|
|
|
927
1101
|
const Parent = new WeakMap();
|
|
928
|
-
const Oops$
|
|
1102
|
+
const Oops$1 = issues({
|
|
929
1103
|
ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
930
1104
|
UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
931
1105
|
UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
|
|
@@ -950,7 +1124,7 @@ function use(input, argument) {
|
|
|
950
1124
|
let current;
|
|
951
1125
|
const onUpdate = (next, initial) => {
|
|
952
1126
|
if (mode === true && !initial)
|
|
953
|
-
throw Oops$
|
|
1127
|
+
throw Oops$1.IsReadOnly(subject, key);
|
|
954
1128
|
if (next) {
|
|
955
1129
|
current = next instanceof Model
|
|
956
1130
|
? next : bootstrap(next);
|
|
@@ -958,7 +1132,7 @@ function use(input, argument) {
|
|
|
958
1132
|
manage(current);
|
|
959
1133
|
}
|
|
960
1134
|
else if (mode === undefined)
|
|
961
|
-
throw Oops$
|
|
1135
|
+
throw Oops$1.UndefinedNotAllowed(key);
|
|
962
1136
|
else
|
|
963
1137
|
current = undefined;
|
|
964
1138
|
if (typeof argument == "function")
|
|
@@ -970,11 +1144,11 @@ function use(input, argument) {
|
|
|
970
1144
|
input instanceof Model ? input :
|
|
971
1145
|
typeof input === "function" ? input() :
|
|
972
1146
|
typeof input === "object" ? bootstrap(input) :
|
|
973
|
-
Oops$
|
|
1147
|
+
Oops$1.BadArgument(typeof input).throw();
|
|
974
1148
|
if (current)
|
|
975
1149
|
mode = onUpdate(current, true) || mode;
|
|
976
1150
|
else if (mode == true)
|
|
977
|
-
throw Oops$
|
|
1151
|
+
throw Oops$1.MustBeDefined(subject, key);
|
|
978
1152
|
}
|
|
979
1153
|
else
|
|
980
1154
|
mode = false;
|
|
@@ -989,40 +1163,14 @@ function parent(Expects, required) {
|
|
|
989
1163
|
const value = Parent.get(this.subject);
|
|
990
1164
|
if (!value) {
|
|
991
1165
|
if (required)
|
|
992
|
-
throw Oops$
|
|
1166
|
+
throw Oops$1.ParentRequired(expected, child);
|
|
993
1167
|
}
|
|
994
1168
|
else if (!(value instanceof Expects))
|
|
995
|
-
throw Oops$
|
|
1169
|
+
throw Oops$1.UnexpectedParent(expected, child, value);
|
|
996
1170
|
return { value };
|
|
997
1171
|
});
|
|
998
1172
|
}
|
|
999
1173
|
|
|
1000
|
-
const Oops$2 = issues({
|
|
1001
|
-
DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
|
|
1002
|
-
BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
1003
|
-
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
|
|
1004
|
-
});
|
|
1005
|
-
function createRef(key, cb) {
|
|
1006
|
-
const refObjectFunction = this.setter(key, cb && createValueEffect(cb));
|
|
1007
|
-
defineProperty(refObjectFunction, "current", {
|
|
1008
|
-
set: refObjectFunction,
|
|
1009
|
-
get: () => this.state[key]
|
|
1010
|
-
});
|
|
1011
|
-
return refObjectFunction;
|
|
1012
|
-
}
|
|
1013
|
-
function ref(arg) {
|
|
1014
|
-
return apply(function ref(key) {
|
|
1015
|
-
let value = {};
|
|
1016
|
-
if (typeof arg == "object") {
|
|
1017
|
-
const source = manage(arg);
|
|
1018
|
-
for (const key in source.state)
|
|
1019
|
-
defineLazy(value, key, createRef.bind(source, key));
|
|
1020
|
-
}
|
|
1021
|
-
else
|
|
1022
|
-
value = createRef.call(this, key, arg);
|
|
1023
|
-
return { value };
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
1174
|
function on(initial, cb) {
|
|
1027
1175
|
return apply(function on(key) {
|
|
1028
1176
|
this.manage(key, initial, cb && createValueEffect(cb));
|
|
@@ -1046,132 +1194,6 @@ function lazy(value) {
|
|
|
1046
1194
|
get: () => source[key]
|
|
1047
1195
|
});
|
|
1048
1196
|
});
|
|
1049
|
-
}
|
|
1050
|
-
function act(task) {
|
|
1051
|
-
return apply(function act(key) {
|
|
1052
|
-
let pending = false;
|
|
1053
|
-
const invoke = (...args) => {
|
|
1054
|
-
if (pending)
|
|
1055
|
-
return Promise.reject(Oops$2.DuplicateAction(key));
|
|
1056
|
-
pending = true;
|
|
1057
|
-
this.update(key);
|
|
1058
|
-
return new Promise(res => {
|
|
1059
|
-
res(task.apply(this.subject, args));
|
|
1060
|
-
}).finally(() => {
|
|
1061
|
-
pending = false;
|
|
1062
|
-
this.update(key);
|
|
1063
|
-
});
|
|
1064
|
-
};
|
|
1065
|
-
setAlias(invoke, `run ${key}`);
|
|
1066
|
-
defineProperty(invoke, "active", {
|
|
1067
|
-
get: () => pending
|
|
1068
|
-
});
|
|
1069
|
-
return {
|
|
1070
|
-
value: invoke,
|
|
1071
|
-
writable: false
|
|
1072
|
-
};
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
|
-
function from(source, setter, getter) {
|
|
1076
|
-
return apply(function from(key) {
|
|
1077
|
-
const { subject } = this;
|
|
1078
|
-
let getSource;
|
|
1079
|
-
// Easy mistake, using a peer, will always be unresolved.
|
|
1080
|
-
if (typeof source == "symbol")
|
|
1081
|
-
throw Oops$2.PeerNotAllowed(subject, key);
|
|
1082
|
-
// replace source controller in-case different
|
|
1083
|
-
if (typeof source == "object")
|
|
1084
|
-
getSource = () => manage(source);
|
|
1085
|
-
// specifically an arrow function (getter factory)
|
|
1086
|
-
else if (!source.prototype) {
|
|
1087
|
-
setter = source.call(subject, key);
|
|
1088
|
-
getSource = () => this;
|
|
1089
|
-
}
|
|
1090
|
-
// is a peer Model (constructor)
|
|
1091
|
-
else if (Model.isTypeof(source))
|
|
1092
|
-
getSource = pendingAccess(subject, source, key, true);
|
|
1093
|
-
// Regular function is to ambiguous so not allowed.
|
|
1094
|
-
else
|
|
1095
|
-
throw Oops$2.BadComputedSource(subject, key, source);
|
|
1096
|
-
prepare(this, key, getSource, setter, getter);
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
const Oops$1 = issues({
|
|
1101
|
-
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1102
|
-
});
|
|
1103
|
-
function pending(source, compute) {
|
|
1104
|
-
return (source === undefined ?
|
|
1105
|
-
suspendForValue() :
|
|
1106
|
-
typeof source == "function" && !source.prototype ?
|
|
1107
|
-
suspendForAsync(source) :
|
|
1108
|
-
suspendForComputed(source, compute));
|
|
1109
|
-
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Get value, suspend instead if undefined.
|
|
1112
|
-
*
|
|
1113
|
-
* Throws suspense promise also interpretable as an error.
|
|
1114
|
-
* React could handle it but other contexts probably not.
|
|
1115
|
-
*/
|
|
1116
|
-
function pendingValue(via, key) {
|
|
1117
|
-
const value = via.state[key];
|
|
1118
|
-
if (value !== undefined)
|
|
1119
|
-
return value;
|
|
1120
|
-
const error = Oops$1.ValueNotReady(via.subject, key);
|
|
1121
|
-
const promise = new Promise(resolve => {
|
|
1122
|
-
const release = via.addListener({
|
|
1123
|
-
[key](value) {
|
|
1124
|
-
if (value !== undefined) {
|
|
1125
|
-
release();
|
|
1126
|
-
resolve();
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
});
|
|
1130
|
-
});
|
|
1131
|
-
throw Object.assign(promise, {
|
|
1132
|
-
toString: () => String(error),
|
|
1133
|
-
message: error.message,
|
|
1134
|
-
stack: error.stack
|
|
1135
|
-
});
|
|
1136
|
-
}
|
|
1137
|
-
function suspendForComputed(source, compute) {
|
|
1138
|
-
function getter(_value, key) {
|
|
1139
|
-
return pendingValue(manage(this), key);
|
|
1140
|
-
}
|
|
1141
|
-
return from(source, compute, getter);
|
|
1142
|
-
}
|
|
1143
|
-
function suspendForValue() {
|
|
1144
|
-
return apply(function pending(key) {
|
|
1145
|
-
this.state[key] = undefined;
|
|
1146
|
-
return {
|
|
1147
|
-
set: this.setter(key),
|
|
1148
|
-
get: () => pendingValue(this, key)
|
|
1149
|
-
};
|
|
1150
|
-
});
|
|
1151
|
-
}
|
|
1152
|
-
function suspendForAsync(source) {
|
|
1153
|
-
return apply(function suspense(key) {
|
|
1154
|
-
const subject = this.subject;
|
|
1155
|
-
let waiting = true;
|
|
1156
|
-
let value;
|
|
1157
|
-
let error;
|
|
1158
|
-
return () => {
|
|
1159
|
-
if (error)
|
|
1160
|
-
throw error;
|
|
1161
|
-
if (!waiting)
|
|
1162
|
-
return value;
|
|
1163
|
-
const issue = Oops$1.ValueNotReady(subject, key);
|
|
1164
|
-
let suspend = source
|
|
1165
|
-
.call(subject, key)
|
|
1166
|
-
.catch(err => error = err)
|
|
1167
|
-
.then(out => value = out)
|
|
1168
|
-
.finally(() => waiting = false);
|
|
1169
|
-
throw Object.assign(suspend, {
|
|
1170
|
-
message: issue.message,
|
|
1171
|
-
stack: issue.stack
|
|
1172
|
-
});
|
|
1173
|
-
};
|
|
1174
|
-
});
|
|
1175
1197
|
}
|
|
1176
1198
|
|
|
1177
1199
|
const Oops = issues({
|