@expressive/mvc 1.0.0-beta.33 → 1.0.0-beta.36
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 +841 -823
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +847 -825
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/types/context.d.ts +2 -2
- package/types/index.d.ts +1 -2
- package/types/instructions.d.ts +49 -62
- package/types/lifecycle.d.ts +13 -11
- package/types/model.d.ts +81 -147
- package/types/types.d.ts +1 -15
- package/types/selector.ts +0 -47
package/lib/index.js
CHANGED
|
@@ -2,7 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
|
+
|
|
11
|
+
/*! *****************************************************************************
|
|
12
|
+
Copyright (c) Microsoft Corporation.
|
|
13
|
+
|
|
14
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
15
|
+
purpose with or without fee is hereby granted.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
18
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
19
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
20
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
21
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
22
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
23
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
24
|
+
***************************************************************************** */
|
|
25
|
+
|
|
26
|
+
function __rest(s, e) {
|
|
27
|
+
var t = {};
|
|
28
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
29
|
+
t[p] = s[p];
|
|
30
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
31
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
32
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
33
|
+
t[p[i]] = s[p[i]];
|
|
34
|
+
}
|
|
35
|
+
return t;
|
|
36
|
+
}
|
|
6
37
|
|
|
7
38
|
class Issue extends Error {
|
|
8
39
|
constructor() {
|
|
@@ -13,9 +44,6 @@ class Issue extends Error {
|
|
|
13
44
|
warn() {
|
|
14
45
|
console.warn(this.message);
|
|
15
46
|
}
|
|
16
|
-
throw() {
|
|
17
|
-
throw this;
|
|
18
|
-
}
|
|
19
47
|
}
|
|
20
48
|
function issues(register) {
|
|
21
49
|
const Library = {};
|
|
@@ -27,7 +55,7 @@ function issues(register) {
|
|
|
27
55
|
const Oops$9 = issues({
|
|
28
56
|
BadEffectCallback: () => `Callback for effect-callback may only return a function.`
|
|
29
57
|
});
|
|
30
|
-
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys
|
|
58
|
+
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertyDescriptors, getOwnPropertySymbols, keys, values } = Object;
|
|
31
59
|
function define(target, key, value) {
|
|
32
60
|
defineProperty(target, key, { value });
|
|
33
61
|
}
|
|
@@ -61,7 +89,7 @@ function createValueEffect(callback) {
|
|
|
61
89
|
return function (value) {
|
|
62
90
|
if (typeof unSet == "function")
|
|
63
91
|
unSet(value);
|
|
64
|
-
const out = callback.call(this, value);
|
|
92
|
+
const out = callback.call(this, value, this);
|
|
65
93
|
if (typeof out == "boolean")
|
|
66
94
|
return out;
|
|
67
95
|
if (!out || out instanceof Promise)
|
|
@@ -71,93 +99,185 @@ function createValueEffect(callback) {
|
|
|
71
99
|
else
|
|
72
100
|
throw Oops$9.BadEffectCallback();
|
|
73
101
|
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const Oops$8 = issues({
|
|
105
|
+
StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
|
|
106
|
+
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
107
|
+
});
|
|
108
|
+
class Controller {
|
|
109
|
+
constructor(subject) {
|
|
110
|
+
this.subject = subject;
|
|
111
|
+
this.frame = new Set();
|
|
112
|
+
this.waiting = new Set();
|
|
113
|
+
this.followers = new Set();
|
|
114
|
+
}
|
|
115
|
+
start() {
|
|
116
|
+
this.state = {};
|
|
117
|
+
for (const key in this.subject)
|
|
118
|
+
this.manage(key);
|
|
119
|
+
const handle = new Set(this.waiting);
|
|
120
|
+
this.waiting.clear();
|
|
121
|
+
handle.forEach(cb => cb([]));
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
manage(key, handler) {
|
|
125
|
+
const { state, subject } = this;
|
|
126
|
+
const desc = getOwnPropertyDescriptor(subject, key);
|
|
127
|
+
if (desc && "value" in desc) {
|
|
128
|
+
const { value } = desc;
|
|
129
|
+
const instruction = Pending.get(value);
|
|
130
|
+
if (instruction) {
|
|
131
|
+
Pending.delete(value);
|
|
132
|
+
delete subject[key];
|
|
133
|
+
instruction.call(this, key, this);
|
|
89
134
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
135
|
+
else if (typeof value !== "function" || /^[A-Z]/.test(key)) {
|
|
136
|
+
state[key] = value;
|
|
137
|
+
defineProperty(subject, key, {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
get: () => state[key],
|
|
140
|
+
set: this.setter(key, handler)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
setter(key, handler) {
|
|
146
|
+
const { state, subject } = this;
|
|
147
|
+
return (value) => {
|
|
148
|
+
if (state[key] == value)
|
|
149
|
+
return;
|
|
150
|
+
if (handler)
|
|
151
|
+
switch (handler.call(subject, value, state)) {
|
|
152
|
+
case true:
|
|
153
|
+
this.update(key);
|
|
154
|
+
case false:
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.update(key, value);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
addListener(listener) {
|
|
161
|
+
this.followers.add(listener);
|
|
162
|
+
return () => {
|
|
163
|
+
this.followers.delete(listener);
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
update(key, value) {
|
|
167
|
+
if (1 in arguments)
|
|
168
|
+
this.state[key] = value;
|
|
169
|
+
if (this.frame.has(key))
|
|
170
|
+
return;
|
|
171
|
+
if (!this.frame.size)
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
flush(this);
|
|
174
|
+
const keys = Object.freeze([...this.frame]);
|
|
175
|
+
const handle = new Set(this.waiting);
|
|
176
|
+
this.waiting.clear();
|
|
177
|
+
this.frame.clear();
|
|
178
|
+
UPDATE.set(this.subject, keys);
|
|
179
|
+
setTimeout(() => {
|
|
180
|
+
UPDATE.delete(this.subject);
|
|
181
|
+
}, 0);
|
|
182
|
+
handle.forEach(callback => {
|
|
183
|
+
try {
|
|
184
|
+
callback(keys);
|
|
185
|
+
}
|
|
186
|
+
catch (e) { }
|
|
187
|
+
});
|
|
188
|
+
}, 0);
|
|
189
|
+
this.frame.add(key);
|
|
190
|
+
for (const callback of this.followers) {
|
|
191
|
+
const event = callback(key, this);
|
|
192
|
+
if (typeof event == "function")
|
|
193
|
+
this.waiting.add(event);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
requestUpdate(arg) {
|
|
197
|
+
if (typeof arg == "function") {
|
|
198
|
+
this.waiting.add(arg);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (typeof arg == "boolean" && arg !== this.frame.size > 0)
|
|
202
|
+
return Promise.reject(Oops$8.StrictUpdate(arg));
|
|
203
|
+
return {
|
|
204
|
+
then: (callback) => {
|
|
205
|
+
if (callback)
|
|
206
|
+
if (this.frame.size)
|
|
207
|
+
this.waiting.add(callback);
|
|
208
|
+
else
|
|
209
|
+
callback(false);
|
|
210
|
+
else
|
|
211
|
+
throw Oops$8.NoChaining();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
93
215
|
}
|
|
94
216
|
|
|
95
217
|
class Subscriber {
|
|
96
218
|
constructor(parent, onUpdate) {
|
|
97
219
|
this.onUpdate = onUpdate;
|
|
98
220
|
this.active = false;
|
|
99
|
-
this.
|
|
221
|
+
this.watch = {};
|
|
100
222
|
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
|
-
};
|
|
120
223
|
if (!(parent instanceof Controller))
|
|
121
|
-
parent =
|
|
224
|
+
parent = getController(parent);
|
|
122
225
|
this.parent = parent;
|
|
123
226
|
this.source = parent.subject;
|
|
124
|
-
this.proxy = create(parent.subject);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
for (const key in parent.state)
|
|
128
|
-
this.spy(key);
|
|
129
|
-
}
|
|
130
|
-
spy(key) {
|
|
131
|
-
const { proxy, source } = this;
|
|
132
|
-
const { set } = getOwnPropertyDescriptor(source, key);
|
|
133
|
-
const intercept = () => {
|
|
134
|
-
this.follow(key);
|
|
135
|
-
delete proxy[key];
|
|
136
|
-
return proxy[key];
|
|
227
|
+
const proxy = this.proxy = create(parent.subject);
|
|
228
|
+
const DEBUG = (keys) => {
|
|
229
|
+
UPDATE.set(proxy, keys.filter(k => k in this.watch));
|
|
137
230
|
};
|
|
138
|
-
|
|
139
|
-
defineProperty(
|
|
140
|
-
get:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
231
|
+
define(proxy, LOCAL, this);
|
|
232
|
+
defineProperty(this, "proxy", {
|
|
233
|
+
get: () => {
|
|
234
|
+
if (UPDATE.has(proxy))
|
|
235
|
+
setTimeout(() => {
|
|
236
|
+
UPDATE.delete(proxy);
|
|
237
|
+
}, 0);
|
|
238
|
+
return proxy;
|
|
239
|
+
}
|
|
144
240
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
241
|
+
for (const key in parent.state) {
|
|
242
|
+
const existing = getOwnPropertyDescriptor(parent.subject, key);
|
|
243
|
+
const isUsing = () => {
|
|
244
|
+
this.watch[key] = true;
|
|
245
|
+
delete proxy[key];
|
|
246
|
+
return proxy[key];
|
|
247
|
+
};
|
|
248
|
+
setAlias(isUsing, `tap ${key}`);
|
|
249
|
+
defineProperty(proxy, key, {
|
|
250
|
+
set: existing.set,
|
|
251
|
+
get: isUsing,
|
|
252
|
+
configurable: true,
|
|
253
|
+
enumerable: true
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
this.commit = () => {
|
|
257
|
+
const { parent } = this;
|
|
258
|
+
const onDone = parent.addListener(key => {
|
|
259
|
+
const handler = this.watch[key];
|
|
260
|
+
if (!handler)
|
|
261
|
+
return;
|
|
262
|
+
if (typeof handler == "function")
|
|
263
|
+
handler();
|
|
264
|
+
const notify = this.onUpdate(key, parent);
|
|
265
|
+
if (notify) {
|
|
266
|
+
parent.requestUpdate(DEBUG);
|
|
267
|
+
parent.requestUpdate(notify);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
this.active = true;
|
|
271
|
+
this.dependant.forEach(x => x.commit());
|
|
272
|
+
return this.release = () => {
|
|
273
|
+
this.dependant.forEach(x => x.release());
|
|
274
|
+
onDone();
|
|
275
|
+
};
|
|
156
276
|
};
|
|
157
277
|
}
|
|
158
278
|
}
|
|
159
279
|
|
|
160
|
-
const Oops$
|
|
280
|
+
const Oops$7 = issues({
|
|
161
281
|
ComputeFailed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`,
|
|
162
282
|
ComputedEarly: (property) => `Note: Computed values don't run until accessed, except when subscribed to. '${property}' getter may have run earlier than intended.`
|
|
163
283
|
});
|
|
@@ -183,7 +303,7 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
183
303
|
return setter.call(sub.proxy, sub.proxy);
|
|
184
304
|
}
|
|
185
305
|
catch (err) {
|
|
186
|
-
Oops$
|
|
306
|
+
Oops$7.ComputeFailed(subject, key, !!initial).warn();
|
|
187
307
|
throw err;
|
|
188
308
|
}
|
|
189
309
|
}
|
|
@@ -229,12 +349,12 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
229
349
|
}
|
|
230
350
|
catch (e) {
|
|
231
351
|
if (early)
|
|
232
|
-
Oops$
|
|
352
|
+
Oops$7.ComputedEarly(key).warn();
|
|
233
353
|
throw e;
|
|
234
354
|
}
|
|
235
355
|
finally {
|
|
236
356
|
sub.commit();
|
|
237
|
-
for (const key in sub.
|
|
357
|
+
for (const key in sub.watch) {
|
|
238
358
|
const peer = register.get(key);
|
|
239
359
|
if (peer && peer.priority >= info.priority)
|
|
240
360
|
info.priority = peer.priority + 1;
|
|
@@ -254,7 +374,7 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
254
374
|
enumerable: true
|
|
255
375
|
});
|
|
256
376
|
}
|
|
257
|
-
function ensure(on, keys) {
|
|
377
|
+
function ensure$1(on, keys) {
|
|
258
378
|
for (const key of keys) {
|
|
259
379
|
const desc = getOwnPropertyDescriptor(on.subject, key);
|
|
260
380
|
const getter = desc && desc.get;
|
|
@@ -277,6 +397,287 @@ function flush(on) {
|
|
|
277
397
|
KEYS.delete(on);
|
|
278
398
|
}
|
|
279
399
|
|
|
400
|
+
const CONTROL = Symbol("CONTROL");
|
|
401
|
+
const WHY = Symbol("UPDATE");
|
|
402
|
+
const LOCAL = Symbol("LOCAL");
|
|
403
|
+
const STATE = Symbol("STATE");
|
|
404
|
+
const UPDATE = new WeakMap();
|
|
405
|
+
function ensure(subject, callback) {
|
|
406
|
+
const control = subject[CONTROL];
|
|
407
|
+
if (!control.state) {
|
|
408
|
+
let done;
|
|
409
|
+
control.requestUpdate(() => {
|
|
410
|
+
done = callback(control);
|
|
411
|
+
});
|
|
412
|
+
return () => done();
|
|
413
|
+
}
|
|
414
|
+
return callback(control);
|
|
415
|
+
}
|
|
416
|
+
function getController(subject) {
|
|
417
|
+
const control = subject[CONTROL];
|
|
418
|
+
if (!control.state)
|
|
419
|
+
control.start();
|
|
420
|
+
if (subject.didCreate)
|
|
421
|
+
subject.didCreate();
|
|
422
|
+
return control;
|
|
423
|
+
}
|
|
424
|
+
class Model {
|
|
425
|
+
constructor() {
|
|
426
|
+
define(this, CONTROL, new Controller(this));
|
|
427
|
+
define(this, "get", this);
|
|
428
|
+
define(this, "set", this);
|
|
429
|
+
}
|
|
430
|
+
get [STATE]() {
|
|
431
|
+
return this[CONTROL].state;
|
|
432
|
+
}
|
|
433
|
+
get [WHY]() {
|
|
434
|
+
return UPDATE.get(this);
|
|
435
|
+
}
|
|
436
|
+
on(select, handler, squash, once) {
|
|
437
|
+
return ensure(this, control => {
|
|
438
|
+
const keys = typeof select == "string" ? [select] :
|
|
439
|
+
!select.length ? getOwnPropertyNames(control.state) :
|
|
440
|
+
select;
|
|
441
|
+
ensure$1(control, keys);
|
|
442
|
+
const callback = squash
|
|
443
|
+
? handler.bind(this)
|
|
444
|
+
: frame => frame
|
|
445
|
+
.filter(k => keys.includes(k))
|
|
446
|
+
.forEach(k => handler.call(this, control.state[k], k));
|
|
447
|
+
const trigger = once
|
|
448
|
+
? frame => { remove(); callback(frame); }
|
|
449
|
+
: callback;
|
|
450
|
+
const remove = control.addListener(key => {
|
|
451
|
+
if (keys.includes(key))
|
|
452
|
+
return trigger;
|
|
453
|
+
});
|
|
454
|
+
return remove;
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
once(select, callback, squash) {
|
|
458
|
+
if (callback)
|
|
459
|
+
return this.on(select, callback, squash, true);
|
|
460
|
+
return new Promise(resolve => {
|
|
461
|
+
this.on(select, resolve, true, true);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
effect(callback, select) {
|
|
465
|
+
const effect = createEffect(callback);
|
|
466
|
+
return ensure(this, control => {
|
|
467
|
+
if (!select) {
|
|
468
|
+
const sub = new Subscriber(control, () => invoke);
|
|
469
|
+
const invoke = () => {
|
|
470
|
+
const x = sub.proxy;
|
|
471
|
+
effect.call(x, x);
|
|
472
|
+
};
|
|
473
|
+
invoke();
|
|
474
|
+
return sub.commit();
|
|
475
|
+
}
|
|
476
|
+
const invoke = () => {
|
|
477
|
+
effect.call(this.get, this.get);
|
|
478
|
+
};
|
|
479
|
+
invoke();
|
|
480
|
+
if (!select.length)
|
|
481
|
+
select.push("willDestroy");
|
|
482
|
+
return control.addListener(key => {
|
|
483
|
+
if (select.includes(key))
|
|
484
|
+
return invoke;
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
import(from, subset) {
|
|
489
|
+
for (const key of subset || getOwnPropertyNames(this))
|
|
490
|
+
if (key in from)
|
|
491
|
+
this[key] = from[key];
|
|
492
|
+
}
|
|
493
|
+
export(subset) {
|
|
494
|
+
const { state } = getController(this);
|
|
495
|
+
const output = {};
|
|
496
|
+
for (const key of subset || getOwnPropertyNames(state))
|
|
497
|
+
output[key] = state[key];
|
|
498
|
+
return output;
|
|
499
|
+
}
|
|
500
|
+
update(arg, tag) {
|
|
501
|
+
const control = getController(this);
|
|
502
|
+
if (typeof arg == "string") {
|
|
503
|
+
control.update(arg);
|
|
504
|
+
if (1 in arguments && arg in this) {
|
|
505
|
+
const method = this[arg];
|
|
506
|
+
if (typeof method == "function")
|
|
507
|
+
if (typeof tag != "boolean")
|
|
508
|
+
method.call(this, tag);
|
|
509
|
+
else if (tag)
|
|
510
|
+
method.call(this);
|
|
511
|
+
}
|
|
512
|
+
arg = undefined;
|
|
513
|
+
}
|
|
514
|
+
return control.requestUpdate(arg);
|
|
515
|
+
}
|
|
516
|
+
destroy() {
|
|
517
|
+
this.update("willDestroy", true);
|
|
518
|
+
}
|
|
519
|
+
toString() {
|
|
520
|
+
return this.constructor.name;
|
|
521
|
+
}
|
|
522
|
+
static create(...args) {
|
|
523
|
+
const instance = new this(...args);
|
|
524
|
+
getController(instance);
|
|
525
|
+
return instance;
|
|
526
|
+
}
|
|
527
|
+
static isTypeof(maybe) {
|
|
528
|
+
return (typeof maybe == "function" &&
|
|
529
|
+
maybe.prototype instanceof this);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
Model.CONTROL = CONTROL;
|
|
533
|
+
Model.STATE = STATE;
|
|
534
|
+
Model.LOCAL = LOCAL;
|
|
535
|
+
Model.WHY = WHY;
|
|
536
|
+
defineLazy(Model, CONTROL, function () {
|
|
537
|
+
return new Controller(this);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
const Pending = new Map();
|
|
541
|
+
function apply(fn, label) {
|
|
542
|
+
const name = label || fn.name || "pending";
|
|
543
|
+
const placeholder = Symbol(`${name} instruction`);
|
|
544
|
+
function setup(key) {
|
|
545
|
+
const { subject, state } = this;
|
|
546
|
+
let output = fn.call(this, key, this);
|
|
547
|
+
let desc = {};
|
|
548
|
+
let get;
|
|
549
|
+
let set;
|
|
550
|
+
if (!output)
|
|
551
|
+
return;
|
|
552
|
+
if (typeof output == "function")
|
|
553
|
+
get = output;
|
|
554
|
+
else {
|
|
555
|
+
(({ get, set } = output), desc = __rest(output, ["get", "set"]));
|
|
556
|
+
if ("value" in desc) {
|
|
557
|
+
state[key] = desc.value;
|
|
558
|
+
if (get || set)
|
|
559
|
+
delete desc.value;
|
|
560
|
+
else {
|
|
561
|
+
defineProperty(subject, key, desc);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
defineProperty(subject, key, Object.assign(Object.assign({}, desc), { set: this.setter(key, set), get: get
|
|
567
|
+
? function () {
|
|
568
|
+
return get(state[key], this[LOCAL]);
|
|
569
|
+
}
|
|
570
|
+
: () => state[key] }));
|
|
571
|
+
}
|
|
572
|
+
Pending.set(placeholder, setup);
|
|
573
|
+
return placeholder;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
//TODO: sync instruction
|
|
577
|
+
function child(source, name) {
|
|
578
|
+
return apply(function child(key) {
|
|
579
|
+
const context = new WeakMap();
|
|
580
|
+
const peer = source.call(this, key);
|
|
581
|
+
function subscribe(sub) {
|
|
582
|
+
let child;
|
|
583
|
+
function init() {
|
|
584
|
+
if (child) {
|
|
585
|
+
child.release();
|
|
586
|
+
sub.dependant.delete(child);
|
|
587
|
+
context.set(sub, undefined);
|
|
588
|
+
child = undefined;
|
|
589
|
+
}
|
|
590
|
+
const instance = peer.get();
|
|
591
|
+
if (instance) {
|
|
592
|
+
child = new Subscriber(instance, sub.onUpdate);
|
|
593
|
+
if (sub.active)
|
|
594
|
+
child.commit();
|
|
595
|
+
sub.dependant.add(child);
|
|
596
|
+
context.set(sub, child.proxy);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
init();
|
|
600
|
+
sub.watch[key] = init;
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
value: peer.get(),
|
|
604
|
+
set: peer.set,
|
|
605
|
+
get(_value, local) {
|
|
606
|
+
if (!local)
|
|
607
|
+
return peer.get();
|
|
608
|
+
if (!context.has(local))
|
|
609
|
+
subscribe(local);
|
|
610
|
+
return context.get(local);
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
}, name || source.name);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
const Parent = new WeakMap();
|
|
617
|
+
const Oops$6 = issues({
|
|
618
|
+
ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
619
|
+
UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
620
|
+
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
621
|
+
});
|
|
622
|
+
function bootstrap(object) {
|
|
623
|
+
const breakdown = getOwnPropertyDescriptors(object);
|
|
624
|
+
const control = new Model();
|
|
625
|
+
for (const key in breakdown)
|
|
626
|
+
defineProperty(control, key, breakdown[key]);
|
|
627
|
+
return control;
|
|
628
|
+
}
|
|
629
|
+
function use$1(input, argument) {
|
|
630
|
+
return child(function use(key) {
|
|
631
|
+
const { subject } = this;
|
|
632
|
+
let current;
|
|
633
|
+
const onUpdate = (next) => {
|
|
634
|
+
if (next) {
|
|
635
|
+
current = next instanceof Model
|
|
636
|
+
? next : bootstrap(next);
|
|
637
|
+
Parent.set(current, subject);
|
|
638
|
+
getController(current);
|
|
639
|
+
}
|
|
640
|
+
else
|
|
641
|
+
current = undefined;
|
|
642
|
+
if (typeof argument == "function")
|
|
643
|
+
return argument(current);
|
|
644
|
+
};
|
|
645
|
+
if (input) {
|
|
646
|
+
const initial = Model.isTypeof(input)
|
|
647
|
+
? new input() :
|
|
648
|
+
input instanceof Model
|
|
649
|
+
? input :
|
|
650
|
+
typeof input === "function"
|
|
651
|
+
? input() :
|
|
652
|
+
typeof input === "object"
|
|
653
|
+
? bootstrap(input)
|
|
654
|
+
: null;
|
|
655
|
+
if (initial)
|
|
656
|
+
onUpdate(initial);
|
|
657
|
+
else if (initial === null)
|
|
658
|
+
throw Oops$6.BadArgument(typeof input);
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
get: () => current,
|
|
662
|
+
set: onUpdate
|
|
663
|
+
};
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
function parent(Expects, required) {
|
|
667
|
+
return apply(function parent() {
|
|
668
|
+
const child = this.subject;
|
|
669
|
+
const expected = Expects.name;
|
|
670
|
+
const value = Parent.get(this.subject);
|
|
671
|
+
if (!value) {
|
|
672
|
+
if (required)
|
|
673
|
+
throw Oops$6.ParentRequired(expected, child);
|
|
674
|
+
}
|
|
675
|
+
else if (!(value instanceof Expects))
|
|
676
|
+
throw Oops$6.UnexpectedParent(expected, child, value);
|
|
677
|
+
return { value };
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
|
|
280
681
|
const Lifecycle = {
|
|
281
682
|
WILL_RENDER: "willRender",
|
|
282
683
|
WILL_UPDATE: "willUpdate",
|
|
@@ -284,7 +685,7 @@ const Lifecycle = {
|
|
|
284
685
|
WILL_UNMOUNT: "willUnmount",
|
|
285
686
|
DID_MOUNT: "didMount"
|
|
286
687
|
};
|
|
287
|
-
|
|
688
|
+
[
|
|
288
689
|
"didCreate",
|
|
289
690
|
"willDestroy",
|
|
290
691
|
...values(Lifecycle)
|
|
@@ -292,7 +693,7 @@ const lifecycleEvents = [
|
|
|
292
693
|
function lifecycle(prefix) {
|
|
293
694
|
const type = eventsFor(prefix);
|
|
294
695
|
return function useLifecycle(sub, tag) {
|
|
295
|
-
const emit =
|
|
696
|
+
const emit = React__default["default"].useMemo(() => {
|
|
296
697
|
const subject = sub.source;
|
|
297
698
|
const id = typeof tag == "function" ? tag(subject) : tag;
|
|
298
699
|
return (name) => {
|
|
@@ -304,7 +705,7 @@ function lifecycle(prefix) {
|
|
|
304
705
|
emit(sub.active
|
|
305
706
|
? Lifecycle.WILL_UPDATE
|
|
306
707
|
: Lifecycle.WILL_MOUNT);
|
|
307
|
-
|
|
708
|
+
React__default["default"].useLayoutEffect(() => {
|
|
308
709
|
sub.commit();
|
|
309
710
|
emit(Lifecycle.DID_MOUNT);
|
|
310
711
|
return () => {
|
|
@@ -318,254 +719,264 @@ function eventsFor(prefix) {
|
|
|
318
719
|
const map = new Map();
|
|
319
720
|
for (const name of values(Lifecycle)) {
|
|
320
721
|
const alias = prefix + name[0].toUpperCase() + name.slice(1);
|
|
321
|
-
lifecycleEvents.push(alias);
|
|
322
722
|
map.set(name, alias);
|
|
323
723
|
}
|
|
324
724
|
return (e) => map.get(e);
|
|
325
725
|
}
|
|
326
726
|
|
|
327
|
-
const
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
727
|
+
const useElementLifecycle = lifecycle("element");
|
|
728
|
+
const useComponentLifecycle = lifecycle("component");
|
|
729
|
+
function use(init) {
|
|
730
|
+
const [state, update] = React__default["default"].useState(() => [
|
|
731
|
+
init(() => update(state.concat()))
|
|
732
|
+
]);
|
|
733
|
+
return state[0];
|
|
333
734
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (typeof output == "function") {
|
|
341
|
-
const getter = output;
|
|
342
|
-
output = Object.assign(Object.assign({}, getOwnPropertyDescriptor(this.subject, key)), { get() {
|
|
343
|
-
return getter(this[LOCAL]);
|
|
344
|
-
} });
|
|
345
|
-
}
|
|
346
|
-
if (output)
|
|
347
|
-
defineProperty(this.subject, key, output);
|
|
348
|
-
}
|
|
349
|
-
Pending.set(placeholder, setup);
|
|
350
|
-
return placeholder;
|
|
735
|
+
function useTap(model, path, expect) {
|
|
736
|
+
if (typeof path == "function")
|
|
737
|
+
return useComputed(model, path, expect);
|
|
738
|
+
const proxy = useActive(model, path, expect);
|
|
739
|
+
model.update("willRender", true);
|
|
740
|
+
return proxy;
|
|
351
741
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
742
|
+
function useTag(model, id) {
|
|
743
|
+
const hook = use(refresh => (new Subscriber(model, () => refresh)));
|
|
744
|
+
useElementLifecycle(hook, id || 0);
|
|
745
|
+
return hook.proxy;
|
|
746
|
+
}
|
|
747
|
+
function useNew(model, callback) {
|
|
748
|
+
const hook = use(refresh => {
|
|
749
|
+
if (callback)
|
|
750
|
+
callback(model);
|
|
751
|
+
return new Subscriber(model, () => refresh);
|
|
752
|
+
});
|
|
753
|
+
useComponentLifecycle(hook);
|
|
754
|
+
return hook.proxy;
|
|
755
|
+
}
|
|
756
|
+
function usePassive(Type, callback) {
|
|
757
|
+
const instance = React__default["default"].useMemo(() => {
|
|
758
|
+
const instance = Type.create();
|
|
759
|
+
if (callback)
|
|
760
|
+
callback(instance);
|
|
761
|
+
return instance;
|
|
762
|
+
}, []);
|
|
763
|
+
React__default["default"].useLayoutEffect(() => () => instance.destroy(), []);
|
|
764
|
+
instance.update("willRender", true);
|
|
765
|
+
return instance;
|
|
766
|
+
}
|
|
767
|
+
function useActive(target, focus, expected) {
|
|
768
|
+
const hook = use(refresh => {
|
|
769
|
+
const sub = new Subscriber(target, () => refresh);
|
|
770
|
+
if (focus) {
|
|
771
|
+
const source = sub.proxy;
|
|
772
|
+
defineProperty(sub, "proxy", {
|
|
773
|
+
get() {
|
|
774
|
+
const value = source[focus];
|
|
775
|
+
if (value === undefined && expected)
|
|
776
|
+
throw suspend(sub.parent, focus);
|
|
777
|
+
return value;
|
|
385
778
|
}
|
|
386
|
-
|
|
387
|
-
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
return sub;
|
|
782
|
+
});
|
|
783
|
+
React__default["default"].useLayoutEffect(() => hook.commit(), []);
|
|
784
|
+
return hook.proxy;
|
|
785
|
+
}
|
|
786
|
+
function useComputed(target, compute, expected) {
|
|
787
|
+
const hook = use(refresh => {
|
|
788
|
+
const sub = new Subscriber(target, () => update);
|
|
789
|
+
const spy = sub.proxy;
|
|
790
|
+
let value = compute.call(spy, spy);
|
|
791
|
+
let update;
|
|
792
|
+
let retry;
|
|
793
|
+
const set = (next) => {
|
|
794
|
+
value = next;
|
|
795
|
+
if (retry) {
|
|
796
|
+
retry();
|
|
797
|
+
retry = undefined;
|
|
388
798
|
}
|
|
799
|
+
else
|
|
800
|
+
refresh();
|
|
801
|
+
};
|
|
802
|
+
if (value instanceof Promise) {
|
|
803
|
+
value.then(set);
|
|
804
|
+
value = undefined;
|
|
389
805
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
806
|
+
else {
|
|
807
|
+
sub.commit();
|
|
808
|
+
update = () => {
|
|
809
|
+
const next = compute.call(spy, spy);
|
|
810
|
+
if (value != next)
|
|
811
|
+
set(next);
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
const get = expected
|
|
815
|
+
? () => {
|
|
816
|
+
if (value === undefined)
|
|
817
|
+
throw new Promise(res => retry = res);
|
|
818
|
+
return value;
|
|
819
|
+
}
|
|
820
|
+
: () => value;
|
|
821
|
+
defineProperty(sub, "proxy", { get });
|
|
822
|
+
return sub;
|
|
823
|
+
});
|
|
824
|
+
React__default["default"].useLayoutEffect(() => hook.release, []);
|
|
825
|
+
return hook.proxy;
|
|
826
|
+
}
|
|
827
|
+
function useModel(Type, callback) {
|
|
828
|
+
const hook = use(refresh => {
|
|
829
|
+
const instance = new Type();
|
|
830
|
+
const sub = new Subscriber(instance, () => refresh);
|
|
831
|
+
const release = sub.parent.addListener((key) => {
|
|
832
|
+
if (key == Lifecycle.WILL_UNMOUNT)
|
|
833
|
+
return () => {
|
|
834
|
+
instance.destroy();
|
|
835
|
+
release();
|
|
836
|
+
};
|
|
407
837
|
});
|
|
838
|
+
if (callback)
|
|
839
|
+
callback(instance);
|
|
840
|
+
return sub;
|
|
841
|
+
});
|
|
842
|
+
useComponentLifecycle(hook);
|
|
843
|
+
usePeerContext(hook.source);
|
|
844
|
+
return hook.proxy;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
class Lookup {
|
|
848
|
+
constructor() {
|
|
849
|
+
this.table = new Map();
|
|
408
850
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
return;
|
|
414
|
-
if (handler)
|
|
415
|
-
switch (handler.call(subject, value)) {
|
|
416
|
-
case true:
|
|
417
|
-
this.update(key);
|
|
418
|
-
case false:
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
this.update(key, value);
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
addListener(listener) {
|
|
425
|
-
this.followers.add(listener);
|
|
426
|
-
return () => {
|
|
427
|
-
this.followers.delete(listener);
|
|
428
|
-
};
|
|
851
|
+
get local() {
|
|
852
|
+
return [
|
|
853
|
+
...new Set(getOwnPropertySymbols(this).map(symbol => this[symbol]))
|
|
854
|
+
];
|
|
429
855
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (!this.frame.size)
|
|
436
|
-
setTimeout(() => this.emit(), 0);
|
|
437
|
-
this.frame.add(key);
|
|
438
|
-
for (const subscription of this.followers) {
|
|
439
|
-
const notify = subscription(key, this);
|
|
440
|
-
if (notify)
|
|
441
|
-
this.waiting.add(notify);
|
|
856
|
+
key(T) {
|
|
857
|
+
let key = this.table.get(T);
|
|
858
|
+
if (!key) {
|
|
859
|
+
key = Symbol(T.name);
|
|
860
|
+
this.table.set(T, key);
|
|
442
861
|
}
|
|
862
|
+
return key;
|
|
443
863
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const keys = Object.freeze([...this.frame]);
|
|
447
|
-
const handle = new Set(this.waiting);
|
|
448
|
-
this.waiting.clear();
|
|
449
|
-
this.frame.clear();
|
|
450
|
-
defineProperty(this.subject, UPDATE, {
|
|
451
|
-
configurable: true,
|
|
452
|
-
value: keys
|
|
453
|
-
});
|
|
454
|
-
handle.forEach(callback => {
|
|
455
|
-
try {
|
|
456
|
-
callback(keys);
|
|
457
|
-
}
|
|
458
|
-
catch (e) { }
|
|
459
|
-
});
|
|
864
|
+
get(T) {
|
|
865
|
+
return this[this.key(T)];
|
|
460
866
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
if (typeof using == "object") {
|
|
466
|
-
using = Array.from(using);
|
|
467
|
-
if (using.length === 0)
|
|
468
|
-
using = undefined;
|
|
867
|
+
push(I) {
|
|
868
|
+
const next = create(this);
|
|
869
|
+
if (I instanceof Model || typeof I == "function")
|
|
870
|
+
next.register(I);
|
|
469
871
|
else
|
|
470
|
-
|
|
872
|
+
for (const i of values(I))
|
|
873
|
+
next.register(i);
|
|
874
|
+
return next;
|
|
471
875
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
const current = source.call(this, key);
|
|
479
|
-
function subscribe(sub) {
|
|
480
|
-
let child;
|
|
481
|
-
function start() {
|
|
482
|
-
const instance = current();
|
|
483
|
-
if (instance) {
|
|
484
|
-
child = new Subscriber(instance, sub.onUpdate);
|
|
485
|
-
if (sub.active)
|
|
486
|
-
child.commit();
|
|
487
|
-
sub.dependant.add(child);
|
|
488
|
-
context.set(sub, child.proxy);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
function restart() {
|
|
492
|
-
if (child) {
|
|
493
|
-
child.release();
|
|
494
|
-
sub.dependant.delete(child);
|
|
495
|
-
context.set(sub, undefined);
|
|
496
|
-
child = undefined;
|
|
497
|
-
}
|
|
498
|
-
start();
|
|
499
|
-
}
|
|
500
|
-
start();
|
|
501
|
-
sub.follow(key, restart);
|
|
876
|
+
register(I) {
|
|
877
|
+
let writable = true;
|
|
878
|
+
let T;
|
|
879
|
+
if (I instanceof Model) {
|
|
880
|
+
T = I.constructor;
|
|
881
|
+
writable = false;
|
|
502
882
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
883
|
+
else {
|
|
884
|
+
T = I;
|
|
885
|
+
I = I.create();
|
|
886
|
+
}
|
|
887
|
+
do {
|
|
888
|
+
const key = this.key(T);
|
|
889
|
+
const conflict = this.hasOwnProperty(key);
|
|
890
|
+
defineProperty(this, key, {
|
|
891
|
+
value: conflict ? null : I,
|
|
892
|
+
configurable: true,
|
|
893
|
+
writable
|
|
894
|
+
});
|
|
895
|
+
T = getPrototypeOf(T);
|
|
896
|
+
} while (T !== Model);
|
|
897
|
+
return I;
|
|
898
|
+
}
|
|
899
|
+
pop() {
|
|
900
|
+
for (const key of getOwnPropertySymbols(this)) {
|
|
901
|
+
const entry = getOwnPropertyDescriptor(this, key);
|
|
902
|
+
if (entry.writable)
|
|
903
|
+
entry.value.destroy();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
511
906
|
}
|
|
512
907
|
|
|
513
|
-
const Oops$
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
908
|
+
const Oops$5 = issues({
|
|
909
|
+
NoProviderType: () => `Provider 'of' prop must be Model, typeof Model or a collection of them.`,
|
|
910
|
+
NothingInContext: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
|
|
911
|
+
BadConsumerProps: () => `Provider expects either a render function, 'get' or 'has' props.`
|
|
517
912
|
});
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
});
|
|
913
|
+
const LookupContext = React__default["default"].createContext(new Lookup());
|
|
914
|
+
const useLookup = () => React__default["default"].useContext(LookupContext);
|
|
915
|
+
function useContext(Type, strict) {
|
|
916
|
+
const instance = useLookup().get(Type);
|
|
917
|
+
if (!instance && strict)
|
|
918
|
+
throw Oops$5.NothingInContext(Type.name);
|
|
919
|
+
return instance;
|
|
526
920
|
}
|
|
527
|
-
function
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
get: onGet
|
|
921
|
+
function Consumer(props) {
|
|
922
|
+
const { get, has, children, of: Control } = props;
|
|
923
|
+
if (typeof children == "function")
|
|
924
|
+
return children(useTap(useContext(Control)));
|
|
925
|
+
const callback = has || get;
|
|
926
|
+
if (typeof callback == "function")
|
|
927
|
+
callback(useContext(Control, !!has));
|
|
928
|
+
else
|
|
929
|
+
throw Oops$5.BadConsumerProps();
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
function useNewContext(inject) {
|
|
933
|
+
const from = useLookup();
|
|
934
|
+
return React__default["default"].useMemo(() => {
|
|
935
|
+
if (!inject)
|
|
936
|
+
throw Oops$5.NoProviderType();
|
|
937
|
+
const context = from.push(inject);
|
|
938
|
+
for (const instance of context.local)
|
|
939
|
+
if (instance)
|
|
940
|
+
for (const apply of getPending(instance))
|
|
941
|
+
apply(context);
|
|
942
|
+
return context;
|
|
943
|
+
}, []);
|
|
944
|
+
}
|
|
945
|
+
function useAppliedProps(within, props) {
|
|
946
|
+
const update = React__default["default"].useMemo(() => {
|
|
947
|
+
const targets = within.local;
|
|
948
|
+
return function integrate(props) {
|
|
949
|
+
for (const [key, value] of entries(props))
|
|
950
|
+
if (key != "of" && key != "children")
|
|
951
|
+
for (const into of targets)
|
|
952
|
+
if (into && key in into)
|
|
953
|
+
into[key] = value;
|
|
561
954
|
};
|
|
955
|
+
}, []);
|
|
956
|
+
update(props);
|
|
957
|
+
}
|
|
958
|
+
function RenderFunction(props) {
|
|
959
|
+
const hook = use(refresh => {
|
|
960
|
+
const targets = props.context.local;
|
|
961
|
+
if (targets.length == 1)
|
|
962
|
+
return new Subscriber(targets[0], () => refresh);
|
|
963
|
+
return {};
|
|
562
964
|
});
|
|
965
|
+
if (hook.commit)
|
|
966
|
+
React__default["default"].useLayoutEffect(() => hook.commit(), []);
|
|
967
|
+
return props.render(hook.proxy);
|
|
563
968
|
}
|
|
564
|
-
function
|
|
565
|
-
|
|
969
|
+
function Provider(props) {
|
|
970
|
+
const context = useNewContext(props.of);
|
|
971
|
+
const render = props.children;
|
|
972
|
+
useAppliedProps(context, props);
|
|
973
|
+
React__default["default"].useLayoutEffect(() => () => context.pop(), []);
|
|
974
|
+
return React__default["default"].createElement(LookupContext.Provider, { value: context }, typeof render == "function"
|
|
975
|
+
? React__default["default"].createElement(RenderFunction, { context, render })
|
|
976
|
+
: render);
|
|
566
977
|
}
|
|
567
978
|
|
|
568
|
-
const Oops$
|
|
979
|
+
const Oops$4 = issues({
|
|
569
980
|
CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
570
981
|
AmbientRequired: (requested, requester, key) => `Attempted to find an instance of ${requested} in context. It is required for [${requester}.${key}], but one could not be found.`
|
|
571
982
|
});
|
|
@@ -573,14 +984,16 @@ const PendingContext = new WeakMap();
|
|
|
573
984
|
const ContextWasUsed = new WeakMap();
|
|
574
985
|
function tap(type, argument) {
|
|
575
986
|
return child(function tap(key) {
|
|
576
|
-
return
|
|
987
|
+
return {
|
|
988
|
+
get: pendingAccess(this.subject, type, key, argument)
|
|
989
|
+
};
|
|
577
990
|
});
|
|
578
991
|
}
|
|
579
992
|
function pendingAccess(from, type, key, argument) {
|
|
580
|
-
if ("
|
|
581
|
-
return () => type.
|
|
582
|
-
if ("
|
|
583
|
-
throw Oops$
|
|
993
|
+
if ("set" in type)
|
|
994
|
+
return () => type.get();
|
|
995
|
+
if ("set" in from.constructor)
|
|
996
|
+
throw Oops$4.CantAttachGlobal(from, type.name);
|
|
584
997
|
let instance;
|
|
585
998
|
getPending(from).push(context => {
|
|
586
999
|
instance = context.get(type);
|
|
@@ -589,7 +1002,7 @@ function pendingAccess(from, type, key, argument) {
|
|
|
589
1002
|
instance = undefined;
|
|
590
1003
|
}
|
|
591
1004
|
else if (!instance && argument)
|
|
592
|
-
throw Oops$
|
|
1005
|
+
throw Oops$4.AmbientRequired(type.name, from, key);
|
|
593
1006
|
});
|
|
594
1007
|
return () => instance;
|
|
595
1008
|
}
|
|
@@ -615,7 +1028,7 @@ function getPending(subject) {
|
|
|
615
1028
|
return pending;
|
|
616
1029
|
}
|
|
617
1030
|
|
|
618
|
-
const Oops$
|
|
1031
|
+
const Oops$3 = issues({
|
|
619
1032
|
DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
|
|
620
1033
|
BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
621
1034
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
|
|
@@ -632,7 +1045,7 @@ function ref(arg) {
|
|
|
632
1045
|
return apply(function ref(key) {
|
|
633
1046
|
let value = {};
|
|
634
1047
|
if (typeof arg == "object") {
|
|
635
|
-
const source =
|
|
1048
|
+
const source = getController(arg);
|
|
636
1049
|
for (const key in source.state)
|
|
637
1050
|
defineLazy(value, key, createRef.bind(source, key));
|
|
638
1051
|
}
|
|
@@ -646,7 +1059,7 @@ function act(task) {
|
|
|
646
1059
|
let pending = false;
|
|
647
1060
|
const invoke = (...args) => {
|
|
648
1061
|
if (pending)
|
|
649
|
-
return Promise.reject(Oops$
|
|
1062
|
+
return Promise.reject(Oops$3.DuplicateAction(key));
|
|
650
1063
|
pending = true;
|
|
651
1064
|
this.update(key);
|
|
652
1065
|
return new Promise(res => {
|
|
@@ -669,17 +1082,17 @@ function act(task) {
|
|
|
669
1082
|
}
|
|
670
1083
|
function from(source, setter, argument) {
|
|
671
1084
|
return apply(function from(key) {
|
|
672
|
-
const { subject } = this;
|
|
673
1085
|
let getSource;
|
|
674
|
-
|
|
1086
|
+
const { subject } = this;
|
|
1087
|
+
const getter = argument === true
|
|
675
1088
|
? pendingValue
|
|
676
1089
|
: argument || undefined;
|
|
677
1090
|
// Easy mistake, using a peer, will always be unresolved.
|
|
678
1091
|
if (typeof source == "symbol")
|
|
679
|
-
throw Oops$
|
|
1092
|
+
throw Oops$3.PeerNotAllowed(subject, key);
|
|
680
1093
|
// replace source controller in-case different
|
|
681
1094
|
if (typeof source == "object")
|
|
682
|
-
getSource = () =>
|
|
1095
|
+
getSource = () => getController(source);
|
|
683
1096
|
// specifically an arrow function (getter factory)
|
|
684
1097
|
else if (!source.prototype) {
|
|
685
1098
|
setter = source.call(subject, key);
|
|
@@ -690,12 +1103,12 @@ function from(source, setter, argument) {
|
|
|
690
1103
|
getSource = pendingAccess(subject, source, key, true);
|
|
691
1104
|
// Regular function is too ambiguous so not allowed.
|
|
692
1105
|
else
|
|
693
|
-
throw Oops$
|
|
1106
|
+
throw Oops$3.BadComputedSource(subject, key, source);
|
|
694
1107
|
prepare(this, key, getSource, setter, getter);
|
|
695
1108
|
});
|
|
696
1109
|
}
|
|
697
1110
|
|
|
698
|
-
const Oops$
|
|
1111
|
+
const Oops$2 = issues({
|
|
699
1112
|
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
700
1113
|
});
|
|
701
1114
|
/* deprecated - ignore coverage */
|
|
@@ -729,423 +1142,130 @@ function pendingFactory(via, key, fn) {
|
|
|
729
1142
|
if (error)
|
|
730
1143
|
throw error;
|
|
731
1144
|
if (key in state)
|
|
732
|
-
return state[key];
|
|
733
|
-
let output;
|
|
734
|
-
try {
|
|
735
|
-
output = fn.call(subject, key, subject);
|
|
736
|
-
}
|
|
737
|
-
catch (err) {
|
|
738
|
-
throw error = err;
|
|
739
|
-
}
|
|
740
|
-
if (output instanceof Promise) {
|
|
741
|
-
const issue = Oops$4.ValueNotReady(subject, key);
|
|
742
|
-
output
|
|
743
|
-
.catch(err => error = err)
|
|
744
|
-
.then(out => state[key] = out)
|
|
745
|
-
.finally(() => waiting = undefined);
|
|
746
|
-
throw waiting = Object.assign(output, {
|
|
747
|
-
message: issue.message,
|
|
748
|
-
stack: issue.stack
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
return state[key] = output;
|
|
753
|
-
}
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
|
-
function suspend(source, key) {
|
|
757
|
-
const error = Oops$4.ValueNotReady(source.subject, key);
|
|
758
|
-
const promise = new Promise(resolve => {
|
|
759
|
-
const release = source.addListener(forKey => {
|
|
760
|
-
if (forKey == key)
|
|
761
|
-
return () => {
|
|
762
|
-
if (source.state[key] !== undefined) {
|
|
763
|
-
release();
|
|
764
|
-
resolve();
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
});
|
|
768
|
-
});
|
|
769
|
-
return Object.assign(promise, {
|
|
770
|
-
toString: () => String(error),
|
|
771
|
-
name: "Suspense",
|
|
772
|
-
message: error.message,
|
|
773
|
-
stack: error.stack
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function use$1(init) {
|
|
778
|
-
const [state, update] = react.useState(() => [
|
|
779
|
-
init(() => update(state.concat()))
|
|
780
|
-
]);
|
|
781
|
-
return state[0];
|
|
782
|
-
}
|
|
783
|
-
function useLazy(Type, callback) {
|
|
784
|
-
const instance = react.useMemo(() => {
|
|
785
|
-
const instance = Type.create();
|
|
786
|
-
if (callback)
|
|
787
|
-
callback(instance);
|
|
788
|
-
return instance;
|
|
789
|
-
}, []);
|
|
790
|
-
react.useLayoutEffect(() => () => instance.destroy(), []);
|
|
791
|
-
return instance;
|
|
792
|
-
}
|
|
793
|
-
function useWatcher(target, focus, expected) {
|
|
794
|
-
const hook = use$1(refresh => {
|
|
795
|
-
const sub = new Subscriber(target, () => refresh);
|
|
796
|
-
if (focus) {
|
|
797
|
-
const source = sub.proxy;
|
|
798
|
-
defineProperty(sub, "proxy", {
|
|
799
|
-
get() {
|
|
800
|
-
const value = source[focus];
|
|
801
|
-
if (value === undefined && expected)
|
|
802
|
-
throw suspend(sub.parent, focus);
|
|
803
|
-
return value;
|
|
804
|
-
}
|
|
805
|
-
});
|
|
806
|
-
}
|
|
807
|
-
return sub;
|
|
808
|
-
});
|
|
809
|
-
react.useLayoutEffect(() => hook.commit(), []);
|
|
810
|
-
return hook.proxy;
|
|
811
|
-
}
|
|
812
|
-
function useComputed(target, compute, expected) {
|
|
813
|
-
const hook = use$1(refresh => {
|
|
814
|
-
const sub = new Subscriber(target, () => update);
|
|
815
|
-
const { proxy } = sub;
|
|
816
|
-
let value;
|
|
817
|
-
let retry;
|
|
818
|
-
const update = () => {
|
|
819
|
-
const next = compute.call(proxy, proxy);
|
|
820
|
-
if (value == next)
|
|
821
|
-
return;
|
|
822
|
-
value = next;
|
|
823
|
-
if (retry) {
|
|
824
|
-
retry();
|
|
825
|
-
retry = undefined;
|
|
826
|
-
}
|
|
827
|
-
else
|
|
828
|
-
refresh();
|
|
829
|
-
};
|
|
830
|
-
const access = () => {
|
|
831
|
-
if (value === undefined && expected)
|
|
832
|
-
throw new Promise(res => {
|
|
833
|
-
retry = res;
|
|
834
|
-
});
|
|
835
|
-
return value;
|
|
836
|
-
};
|
|
837
|
-
value = compute.call(proxy, proxy);
|
|
838
|
-
sub.commit();
|
|
839
|
-
defineProperty(sub, "proxy", { get: access });
|
|
840
|
-
return sub;
|
|
841
|
-
});
|
|
842
|
-
react.useLayoutEffect(() => hook.release, []);
|
|
843
|
-
return hook.proxy;
|
|
844
|
-
}
|
|
845
|
-
function useModel(Type, callback) {
|
|
846
|
-
const hook = use$1(refresh => {
|
|
847
|
-
const instance = new Type();
|
|
848
|
-
const control = manage(instance);
|
|
849
|
-
const sub = new Subscriber(control, () => refresh);
|
|
850
|
-
const release = control.addListener((key) => {
|
|
851
|
-
if (key == Lifecycle.WILL_UNMOUNT)
|
|
852
|
-
return () => {
|
|
853
|
-
instance.destroy();
|
|
854
|
-
release();
|
|
855
|
-
};
|
|
856
|
-
});
|
|
857
|
-
if (callback)
|
|
858
|
-
callback(instance);
|
|
859
|
-
return sub;
|
|
860
|
-
});
|
|
861
|
-
return hook.proxy;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
class Lookup {
|
|
865
|
-
constructor() {
|
|
866
|
-
this.table = new Map();
|
|
867
|
-
}
|
|
868
|
-
get local() {
|
|
869
|
-
return getOwnPropertySymbols(this).map((symbol) => this[symbol]);
|
|
870
|
-
}
|
|
871
|
-
key(T) {
|
|
872
|
-
let key = this.table.get(T);
|
|
873
|
-
if (!key) {
|
|
874
|
-
key = Symbol(T.name);
|
|
875
|
-
this.table.set(T, key);
|
|
876
|
-
}
|
|
877
|
-
return key;
|
|
878
|
-
}
|
|
879
|
-
get(T) {
|
|
880
|
-
return this[this.key(T)];
|
|
881
|
-
}
|
|
882
|
-
push(I) {
|
|
883
|
-
const next = create(this);
|
|
884
|
-
if (I instanceof Model || typeof I == "function")
|
|
885
|
-
next.register(I);
|
|
886
|
-
else
|
|
887
|
-
for (const i of values(I))
|
|
888
|
-
next.register(i);
|
|
889
|
-
return next;
|
|
890
|
-
}
|
|
891
|
-
register(I) {
|
|
892
|
-
let writable = true;
|
|
893
|
-
let T;
|
|
894
|
-
if (I instanceof Model) {
|
|
895
|
-
T = I.constructor;
|
|
896
|
-
writable = false;
|
|
1145
|
+
return state[key];
|
|
1146
|
+
let output;
|
|
1147
|
+
try {
|
|
1148
|
+
output = fn.call(subject, key, subject);
|
|
897
1149
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
I = I.create();
|
|
1150
|
+
catch (err) {
|
|
1151
|
+
throw error = err;
|
|
901
1152
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1153
|
+
if (output instanceof Promise) {
|
|
1154
|
+
const issue = Oops$2.ValueNotReady(subject, key);
|
|
1155
|
+
output
|
|
1156
|
+
.catch(err => error = err)
|
|
1157
|
+
.then(out => state[key] = out)
|
|
1158
|
+
.finally(() => waiting = undefined);
|
|
1159
|
+
throw waiting = Object.assign(output, {
|
|
1160
|
+
message: issue.message,
|
|
1161
|
+
stack: issue.stack
|
|
905
1162
|
});
|
|
906
|
-
T = getPrototypeOf(T);
|
|
907
|
-
} while (T !== Model);
|
|
908
|
-
return I;
|
|
909
|
-
}
|
|
910
|
-
pop() {
|
|
911
|
-
for (const key of getOwnPropertySymbols(this)) {
|
|
912
|
-
const entry = getOwnPropertyDescriptor(this, key);
|
|
913
|
-
if (entry.writable)
|
|
914
|
-
entry.value.destroy();
|
|
915
1163
|
}
|
|
916
|
-
|
|
1164
|
+
else {
|
|
1165
|
+
return state[key] = output;
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function suspend(source, key) {
|
|
1170
|
+
const error = Oops$2.ValueNotReady(source.subject, key);
|
|
1171
|
+
const promise = new Promise(resolve => {
|
|
1172
|
+
const release = source.addListener(forKey => {
|
|
1173
|
+
if (forKey == key)
|
|
1174
|
+
return () => {
|
|
1175
|
+
if (source.state[key] !== undefined) {
|
|
1176
|
+
release();
|
|
1177
|
+
resolve();
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
});
|
|
1181
|
+
});
|
|
1182
|
+
return Object.assign(promise, {
|
|
1183
|
+
toString: () => String(error),
|
|
1184
|
+
name: "Suspense",
|
|
1185
|
+
message: error.message,
|
|
1186
|
+
stack: error.stack
|
|
1187
|
+
});
|
|
917
1188
|
}
|
|
918
1189
|
|
|
919
|
-
const Oops$
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1190
|
+
const Oops$1 = issues({
|
|
1191
|
+
NonOptional: (Parent, key) => `Property ${Parent}.${key} is marked as required.`,
|
|
1192
|
+
BadFactory: () => `Set instruction can only accept a factory or undefined.`,
|
|
1193
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`
|
|
923
1194
|
});
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
932
|
-
function Consumer(props) {
|
|
933
|
-
const { get, has, children, of: Control } = props;
|
|
934
|
-
if (typeof children == "function")
|
|
935
|
-
return children(Control.tap());
|
|
936
|
-
const callback = has || get;
|
|
937
|
-
if (typeof callback == "function")
|
|
938
|
-
callback(Control.get(!!has));
|
|
939
|
-
else
|
|
940
|
-
throw Oops$3.BadConsumerProps();
|
|
941
|
-
return null;
|
|
942
|
-
}
|
|
943
|
-
function useNewContext(from, inject) {
|
|
944
|
-
return react.useMemo(() => {
|
|
945
|
-
if (!inject)
|
|
946
|
-
throw Oops$3.NoProviderType();
|
|
947
|
-
const context = from.push(inject);
|
|
948
|
-
for (const instance of context.local)
|
|
949
|
-
for (const apply of getPending(instance))
|
|
950
|
-
apply(context);
|
|
951
|
-
return context;
|
|
952
|
-
}, []);
|
|
953
|
-
}
|
|
954
|
-
function useAppliedProps(within, props) {
|
|
955
|
-
const update = react.useMemo(() => {
|
|
956
|
-
const targets = within.local;
|
|
957
|
-
return function integrate(props) {
|
|
958
|
-
for (const [key, value] of entries(props))
|
|
959
|
-
if (key != "of" && key != "children")
|
|
960
|
-
for (const into of targets)
|
|
961
|
-
if (key in into)
|
|
962
|
-
into[key] = value;
|
|
963
|
-
};
|
|
964
|
-
}, []);
|
|
965
|
-
update(props);
|
|
1195
|
+
function lazy(value) {
|
|
1196
|
+
return apply(function lazy(key) {
|
|
1197
|
+
const source = this.subject;
|
|
1198
|
+
source[key] = value;
|
|
1199
|
+
defineProperty(this.state, key, {
|
|
1200
|
+
get: () => source[key]
|
|
1201
|
+
});
|
|
1202
|
+
});
|
|
966
1203
|
}
|
|
967
|
-
function
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1204
|
+
function set(factory, argument) {
|
|
1205
|
+
return apply(function set(key) {
|
|
1206
|
+
let set;
|
|
1207
|
+
let get;
|
|
1208
|
+
const required = argument === true || argument === undefined;
|
|
1209
|
+
if (factory === undefined)
|
|
1210
|
+
get = () => pendingValue(this, key);
|
|
1211
|
+
else if (typeof factory !== "function")
|
|
1212
|
+
throw Oops$1.BadFactory();
|
|
1213
|
+
else {
|
|
1214
|
+
get = pendingFactory(this, key, factory);
|
|
1215
|
+
if (required)
|
|
1216
|
+
try {
|
|
1217
|
+
get();
|
|
1218
|
+
}
|
|
1219
|
+
catch (err) {
|
|
1220
|
+
if (err instanceof Promise)
|
|
1221
|
+
;
|
|
1222
|
+
else {
|
|
1223
|
+
Oops$1.FactoryFailed(this.subject, key).warn();
|
|
1224
|
+
throw err;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (typeof argument == "function")
|
|
1229
|
+
set = createValueEffect(argument);
|
|
1230
|
+
else
|
|
1231
|
+
set = (value) => {
|
|
1232
|
+
if (value === undefined && required)
|
|
1233
|
+
throw Oops$1.NonOptional(this.subject, key);
|
|
1234
|
+
};
|
|
1235
|
+
return { set, get };
|
|
973
1236
|
});
|
|
974
|
-
if (hook.commit)
|
|
975
|
-
react.useLayoutEffect(() => hook.commit(), []);
|
|
976
|
-
return props.render(hook.proxy);
|
|
977
1237
|
}
|
|
978
|
-
function
|
|
979
|
-
|
|
980
|
-
const current = useLookup();
|
|
981
|
-
const context = useNewContext(current, props.of);
|
|
982
|
-
useAppliedProps(context, props);
|
|
983
|
-
react.useLayoutEffect(() => () => context.pop(), []);
|
|
984
|
-
return react.createElement(LookupContext.Provider, { value: context }, typeof render == "function"
|
|
985
|
-
? react.createElement(RenderFunction, { context, render })
|
|
986
|
-
: render);
|
|
1238
|
+
function on(initial, onUpdate) {
|
|
1239
|
+
return set(initial && (() => initial), onUpdate);
|
|
987
1240
|
}
|
|
988
1241
|
|
|
989
|
-
|
|
990
|
-
StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
|
|
991
|
-
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
992
|
-
});
|
|
993
|
-
const useElementLifecycle = lifecycle("element");
|
|
994
|
-
const useComponentLifecycle = lifecycle("component");
|
|
995
|
-
class Model {
|
|
996
|
-
constructor() {
|
|
997
|
-
const control = Controller.setup(this);
|
|
998
|
-
define(this, "get", this);
|
|
999
|
-
define(this, "set", this);
|
|
1000
|
-
defer(control, "on");
|
|
1001
|
-
defer(control, "effect");
|
|
1002
|
-
control.waiting.add(() => {
|
|
1003
|
-
delete this.on;
|
|
1004
|
-
delete this.effect;
|
|
1005
|
-
});
|
|
1006
|
-
}
|
|
1242
|
+
class MVC extends Model {
|
|
1007
1243
|
tap(path, expect) {
|
|
1008
|
-
|
|
1009
|
-
return useComputed(this, path, expect);
|
|
1010
|
-
const proxy = useWatcher(this, path, expect);
|
|
1011
|
-
this.update("willRender", true);
|
|
1012
|
-
return proxy;
|
|
1244
|
+
return useTap(this, path, expect);
|
|
1013
1245
|
}
|
|
1014
1246
|
tag(id) {
|
|
1015
|
-
|
|
1016
|
-
useElementLifecycle(hook, id || 0);
|
|
1017
|
-
return hook.proxy;
|
|
1247
|
+
return useTag(this, id);
|
|
1018
1248
|
}
|
|
1019
1249
|
use(callback) {
|
|
1020
|
-
|
|
1021
|
-
if (callback)
|
|
1022
|
-
callback(this);
|
|
1023
|
-
return new Subscriber(this, () => refresh);
|
|
1024
|
-
});
|
|
1025
|
-
useComponentLifecycle(hook);
|
|
1026
|
-
return hook.proxy;
|
|
1027
|
-
}
|
|
1028
|
-
on(subset, handler, squash, once) {
|
|
1029
|
-
const control = manage(this);
|
|
1030
|
-
const request = keys(control, subset);
|
|
1031
|
-
const callback = squash
|
|
1032
|
-
? handler.bind(this)
|
|
1033
|
-
: frame => frame
|
|
1034
|
-
.filter(k => request.includes(k))
|
|
1035
|
-
.forEach(k => handler.call(this, control.state[k], k));
|
|
1036
|
-
const trigger = once
|
|
1037
|
-
? frame => { remove(); callback(frame); }
|
|
1038
|
-
: callback;
|
|
1039
|
-
ensure(control, request);
|
|
1040
|
-
const remove = control.addListener(key => {
|
|
1041
|
-
if (request.includes(key))
|
|
1042
|
-
return trigger;
|
|
1043
|
-
});
|
|
1044
|
-
return remove;
|
|
1045
|
-
}
|
|
1046
|
-
once(select, callback, squash) {
|
|
1047
|
-
if (callback)
|
|
1048
|
-
return this.on(select, callback, squash, true);
|
|
1049
|
-
else
|
|
1050
|
-
return new Promise(resolve => {
|
|
1051
|
-
this.on(select, resolve, true, true);
|
|
1052
|
-
});
|
|
1053
|
-
}
|
|
1054
|
-
effect(callback, select) {
|
|
1055
|
-
const control = manage(this);
|
|
1056
|
-
let target = this;
|
|
1057
|
-
const effect = createEffect(callback);
|
|
1058
|
-
const invoke = () => effect.call(target, target);
|
|
1059
|
-
if (select) {
|
|
1060
|
-
invoke();
|
|
1061
|
-
return this.on(select, invoke, true);
|
|
1062
|
-
}
|
|
1063
|
-
const sub = new Subscriber(control, () => invoke);
|
|
1064
|
-
target = sub.proxy;
|
|
1065
|
-
invoke();
|
|
1066
|
-
return sub.commit();
|
|
1067
|
-
}
|
|
1068
|
-
import(from, subset) {
|
|
1069
|
-
for (const key of keys(manage(this), subset))
|
|
1070
|
-
if (key in from)
|
|
1071
|
-
this[key] = from[key];
|
|
1072
|
-
}
|
|
1073
|
-
export(subset) {
|
|
1074
|
-
const control = manage(this);
|
|
1075
|
-
const output = {};
|
|
1076
|
-
for (const key of keys(control, subset))
|
|
1077
|
-
output[key] = control.state[key];
|
|
1078
|
-
return output;
|
|
1079
|
-
}
|
|
1080
|
-
update(arg, tag) {
|
|
1081
|
-
const control = manage(this);
|
|
1082
|
-
if (typeof arg == "function")
|
|
1083
|
-
arg = select(this, arg);
|
|
1084
|
-
if (typeof arg == "boolean") {
|
|
1085
|
-
if (!control.pending === arg)
|
|
1086
|
-
return Promise.reject(Oops$2.StrictUpdate(arg));
|
|
1087
|
-
}
|
|
1088
|
-
else if (arg) {
|
|
1089
|
-
control.update(arg);
|
|
1090
|
-
if (1 in arguments && arg in this) {
|
|
1091
|
-
const method = this[arg];
|
|
1092
|
-
if (typeof method == "function")
|
|
1093
|
-
if (typeof tag != "boolean")
|
|
1094
|
-
method.call(this, tag);
|
|
1095
|
-
else if (tag)
|
|
1096
|
-
method.call(this);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
return {
|
|
1100
|
-
then(callback) {
|
|
1101
|
-
if (callback)
|
|
1102
|
-
if (control.pending)
|
|
1103
|
-
control.waiting.add(callback);
|
|
1104
|
-
else
|
|
1105
|
-
callback(false);
|
|
1106
|
-
else
|
|
1107
|
-
throw Oops$2.NoChaining();
|
|
1108
|
-
}
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
destroy() {
|
|
1112
|
-
this.update("willDestroy", true);
|
|
1113
|
-
}
|
|
1114
|
-
toString() {
|
|
1115
|
-
return this.constructor.name;
|
|
1116
|
-
}
|
|
1117
|
-
static create(...args) {
|
|
1118
|
-
const instance = new this(...args);
|
|
1119
|
-
manage(instance);
|
|
1120
|
-
return instance;
|
|
1250
|
+
return useNew(this, callback);
|
|
1121
1251
|
}
|
|
1122
1252
|
static new(callback) {
|
|
1123
|
-
|
|
1124
|
-
instance.update("willRender", true);
|
|
1125
|
-
return instance;
|
|
1126
|
-
}
|
|
1127
|
-
static find(strict) {
|
|
1128
|
-
return useFromContext(this, strict);
|
|
1253
|
+
return usePassive(this, callback);
|
|
1129
1254
|
}
|
|
1130
1255
|
static get(key) {
|
|
1131
|
-
const instance = this
|
|
1132
|
-
return (typeof key == "
|
|
1133
|
-
key
|
|
1134
|
-
|
|
1135
|
-
instance[key] :
|
|
1136
|
-
instance);
|
|
1256
|
+
const instance = useContext(this, key !== false);
|
|
1257
|
+
return (typeof key == "string" ?
|
|
1258
|
+
instance[key] :
|
|
1259
|
+
instance);
|
|
1137
1260
|
}
|
|
1138
1261
|
static tap(key, expect) {
|
|
1139
|
-
return this.
|
|
1262
|
+
return this.get().tap(key, expect);
|
|
1140
1263
|
}
|
|
1141
1264
|
static tag(id) {
|
|
1142
|
-
return this.
|
|
1265
|
+
return this.get().tag(id);
|
|
1143
1266
|
}
|
|
1144
1267
|
static use(callback) {
|
|
1145
|
-
|
|
1146
|
-
useComponentLifecycle(instance[LOCAL]);
|
|
1147
|
-
usePeerContext(instance.get);
|
|
1148
|
-
return instance;
|
|
1268
|
+
return useModel(this, callback);
|
|
1149
1269
|
}
|
|
1150
1270
|
static uses(props, only) {
|
|
1151
1271
|
return this.use(instance => {
|
|
@@ -1157,106 +1277,11 @@ class Model {
|
|
|
1157
1277
|
instance.import(props, only);
|
|
1158
1278
|
return instance;
|
|
1159
1279
|
}
|
|
1160
|
-
static meta(path) {
|
|
1280
|
+
static meta(path, expect) {
|
|
1161
1281
|
return typeof path == "function"
|
|
1162
|
-
? useComputed(this, path)
|
|
1163
|
-
:
|
|
1164
|
-
}
|
|
1165
|
-
static isTypeof(maybe) {
|
|
1166
|
-
return (typeof maybe == "function" &&
|
|
1167
|
-
maybe.prototype instanceof this);
|
|
1282
|
+
? useComputed(this, path, expect)
|
|
1283
|
+
: useActive(this, path, expect);
|
|
1168
1284
|
}
|
|
1169
|
-
}
|
|
1170
|
-
Model.CONTROL = CONTROL;
|
|
1171
|
-
Model.STATE = STATE;
|
|
1172
|
-
Model.LOCAL = LOCAL;
|
|
1173
|
-
Model.WHY = UPDATE;
|
|
1174
|
-
defineLazy(Model, CONTROL, function () {
|
|
1175
|
-
return new Controller(this).start();
|
|
1176
|
-
});
|
|
1177
|
-
function defer(on, method) {
|
|
1178
|
-
const { subject, waiting } = on;
|
|
1179
|
-
const real = subject[method];
|
|
1180
|
-
subject[method] = (...args) => {
|
|
1181
|
-
let done;
|
|
1182
|
-
waiting.add(() => {
|
|
1183
|
-
done = real.apply(subject, args);
|
|
1184
|
-
});
|
|
1185
|
-
return () => done();
|
|
1186
|
-
};
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
const Parent = new WeakMap();
|
|
1190
|
-
const Oops$1 = issues({
|
|
1191
|
-
ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1192
|
-
UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1193
|
-
UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
|
|
1194
|
-
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1195
|
-
IsReadOnly: (owner, key) => `${owner}.${key} is set to read-only, but tried to reassign assign.`,
|
|
1196
|
-
MustBeDefined: (owner, key) => `${owner}.${key} must have initial value, as a read-only property.`
|
|
1197
|
-
});
|
|
1198
|
-
function bootstrap(object) {
|
|
1199
|
-
const breakdown = getOwnPropertyDescriptors(object);
|
|
1200
|
-
const control = new Model();
|
|
1201
|
-
for (const key in breakdown)
|
|
1202
|
-
defineProperty(control, key, breakdown[key]);
|
|
1203
|
-
return control;
|
|
1204
|
-
}
|
|
1205
|
-
function use(input, argument) {
|
|
1206
|
-
return child(function use(key) {
|
|
1207
|
-
const { subject } = this;
|
|
1208
|
-
// `true` => readonly
|
|
1209
|
-
// `false` => writable, may be undefined
|
|
1210
|
-
// `undefined` => writable (default)
|
|
1211
|
-
let mode = argument;
|
|
1212
|
-
let current;
|
|
1213
|
-
const onUpdate = (next, initial) => {
|
|
1214
|
-
if (mode === true && !initial)
|
|
1215
|
-
throw Oops$1.IsReadOnly(subject, key);
|
|
1216
|
-
if (next) {
|
|
1217
|
-
current = next instanceof Model
|
|
1218
|
-
? next : bootstrap(next);
|
|
1219
|
-
Parent.set(current, subject);
|
|
1220
|
-
manage(current);
|
|
1221
|
-
}
|
|
1222
|
-
else if (mode === undefined)
|
|
1223
|
-
throw Oops$1.UndefinedNotAllowed(key);
|
|
1224
|
-
else
|
|
1225
|
-
current = undefined;
|
|
1226
|
-
if (typeof argument == "function")
|
|
1227
|
-
return argument(current);
|
|
1228
|
-
};
|
|
1229
|
-
if (input) {
|
|
1230
|
-
current =
|
|
1231
|
-
Model.isTypeof(input) ? new input() :
|
|
1232
|
-
input instanceof Model ? input :
|
|
1233
|
-
typeof input === "function" ? input() :
|
|
1234
|
-
typeof input === "object" ? bootstrap(input) :
|
|
1235
|
-
Oops$1.BadArgument(typeof input).throw();
|
|
1236
|
-
if (current)
|
|
1237
|
-
mode = onUpdate(current, true) || mode;
|
|
1238
|
-
else if (mode == true)
|
|
1239
|
-
throw Oops$1.MustBeDefined(subject, key);
|
|
1240
|
-
}
|
|
1241
|
-
else
|
|
1242
|
-
mode = false;
|
|
1243
|
-
this.manage(key, current, onUpdate);
|
|
1244
|
-
return () => current;
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
function parent(Expects, required) {
|
|
1248
|
-
return apply(function parent() {
|
|
1249
|
-
const child = this.subject;
|
|
1250
|
-
const expected = Expects.name;
|
|
1251
|
-
const value = Parent.get(this.subject);
|
|
1252
|
-
if (!value) {
|
|
1253
|
-
if (required)
|
|
1254
|
-
throw Oops$1.ParentRequired(expected, child);
|
|
1255
|
-
}
|
|
1256
|
-
else if (!(value instanceof Expects))
|
|
1257
|
-
throw Oops$1.UnexpectedParent(expected, child, value);
|
|
1258
|
-
return { value };
|
|
1259
|
-
});
|
|
1260
1285
|
}
|
|
1261
1286
|
|
|
1262
1287
|
const Oops = issues({
|
|
@@ -1264,35 +1289,32 @@ const Oops = issues({
|
|
|
1264
1289
|
GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
|
|
1265
1290
|
});
|
|
1266
1291
|
const Active = new WeakMap();
|
|
1267
|
-
class Singleton extends
|
|
1268
|
-
static get current() {
|
|
1269
|
-
return Active.get(this);
|
|
1270
|
-
}
|
|
1292
|
+
class Singleton extends MVC {
|
|
1271
1293
|
static create(...args) {
|
|
1272
1294
|
const Type = this;
|
|
1273
1295
|
if (Active.has(Type))
|
|
1274
1296
|
throw Oops.GlobalExists(this.name);
|
|
1275
|
-
|
|
1297
|
+
const instance = super.create(...args);
|
|
1276
1298
|
Active.set(Type, instance);
|
|
1277
1299
|
return instance;
|
|
1278
1300
|
}
|
|
1279
|
-
static
|
|
1280
|
-
const instance = this
|
|
1301
|
+
static set(updates) {
|
|
1302
|
+
const instance = Active.get(this) || this.create();
|
|
1281
1303
|
instance.import(updates);
|
|
1282
1304
|
return instance.update();
|
|
1283
1305
|
}
|
|
1284
|
-
static
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
static find(strict) {
|
|
1288
|
-
const instance = this.current;
|
|
1289
|
-
if (!instance && strict)
|
|
1306
|
+
static get(arg) {
|
|
1307
|
+
const instance = Active.get(this);
|
|
1308
|
+
if (!instance && arg !== false)
|
|
1290
1309
|
throw Oops.GlobalDoesNotExist(this.name);
|
|
1291
|
-
return
|
|
1310
|
+
return (typeof arg == "string" ?
|
|
1311
|
+
instance[arg] :
|
|
1312
|
+
instance);
|
|
1292
1313
|
}
|
|
1293
1314
|
static reset() {
|
|
1294
|
-
|
|
1295
|
-
|
|
1315
|
+
const current = Active.get(this);
|
|
1316
|
+
if (current)
|
|
1317
|
+
current.destroy();
|
|
1296
1318
|
}
|
|
1297
1319
|
destroy() {
|
|
1298
1320
|
super.destroy();
|
|
@@ -1301,13 +1323,13 @@ class Singleton extends Model {
|
|
|
1301
1323
|
}
|
|
1302
1324
|
|
|
1303
1325
|
exports.Consumer = Consumer;
|
|
1304
|
-
exports.Model =
|
|
1326
|
+
exports.Model = MVC;
|
|
1305
1327
|
exports.Provider = Provider;
|
|
1306
1328
|
exports.Singleton = Singleton;
|
|
1307
1329
|
exports.act = act;
|
|
1308
1330
|
exports.apply = apply;
|
|
1309
1331
|
exports.child = child;
|
|
1310
|
-
exports["default"] =
|
|
1332
|
+
exports["default"] = MVC;
|
|
1311
1333
|
exports.from = from;
|
|
1312
1334
|
exports.lazy = lazy;
|
|
1313
1335
|
exports.memo = set;
|
|
@@ -1317,5 +1339,5 @@ exports.pending = pending;
|
|
|
1317
1339
|
exports.ref = ref;
|
|
1318
1340
|
exports.set = set;
|
|
1319
1341
|
exports.tap = tap;
|
|
1320
|
-
exports.use = use;
|
|
1342
|
+
exports.use = use$1;
|
|
1321
1343
|
//# sourceMappingURL=index.js.map
|