@expressive/mvc 1.0.0-beta.32 → 1.0.0-beta.35
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 +851 -823
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +869 -836
- 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 +126 -53
- 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 = {};
|
|
@@ -24,10 +52,10 @@ function issues(register) {
|
|
|
24
52
|
return Library;
|
|
25
53
|
}
|
|
26
54
|
|
|
27
|
-
const Oops$
|
|
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
|
}
|
|
@@ -53,7 +81,7 @@ function createEffect(callback) {
|
|
|
53
81
|
if (unSet instanceof Promise)
|
|
54
82
|
unSet = undefined;
|
|
55
83
|
if (unSet && typeof unSet !== "function")
|
|
56
|
-
throw Oops$
|
|
84
|
+
throw Oops$9.BadEffectCallback();
|
|
57
85
|
};
|
|
58
86
|
}
|
|
59
87
|
function createValueEffect(callback) {
|
|
@@ -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)
|
|
@@ -69,95 +97,182 @@ function createValueEffect(callback) {
|
|
|
69
97
|
if (typeof out == "function")
|
|
70
98
|
unSet = out;
|
|
71
99
|
else
|
|
72
|
-
throw Oops$
|
|
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
|
+
setImmediate(() => {
|
|
180
|
+
UPDATE.delete(this.subject);
|
|
181
|
+
});
|
|
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.listen = (key, from) => {
|
|
102
|
-
const handler = this.handle[key];
|
|
103
|
-
if (!handler)
|
|
104
|
-
return;
|
|
105
|
-
if (typeof handler == "function")
|
|
106
|
-
handler();
|
|
107
|
-
const notify = this.onUpdate(key, from);
|
|
108
|
-
if (notify)
|
|
109
|
-
from.waiting.add(notify);
|
|
110
|
-
};
|
|
111
223
|
if (!(parent instanceof Controller))
|
|
112
|
-
parent =
|
|
113
|
-
const subject = this.source =
|
|
114
|
-
parent.subject;
|
|
115
|
-
const proxy = this.proxy =
|
|
116
|
-
create(subject);
|
|
224
|
+
parent = getController(parent);
|
|
117
225
|
this.parent = parent;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
226
|
+
this.source = parent.subject;
|
|
227
|
+
const proxy = this.proxy = create(parent.subject);
|
|
228
|
+
const DEBUG = (keys) => {
|
|
229
|
+
UPDATE.set(proxy, keys.filter(k => k in this.watch));
|
|
230
|
+
};
|
|
231
|
+
define(proxy, LOCAL, this);
|
|
232
|
+
defineProperty(this, "proxy", {
|
|
233
|
+
get: () => {
|
|
234
|
+
if (UPDATE.has(proxy))
|
|
235
|
+
setImmediate(() => {
|
|
236
|
+
UPDATE.delete(proxy);
|
|
237
|
+
});
|
|
238
|
+
return proxy;
|
|
239
|
+
}
|
|
121
240
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
|
130
254
|
});
|
|
131
255
|
}
|
|
132
|
-
|
|
133
|
-
this
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
this.handle[key] = callback || true;
|
|
153
|
-
}
|
|
154
|
-
commit() {
|
|
155
|
-
const onDone = this.parent.addListener(this.listen);
|
|
156
|
-
this.active = true;
|
|
157
|
-
this.dependant.forEach(x => x.commit());
|
|
158
|
-
return this.release = () => {
|
|
159
|
-
this.dependant.forEach(x => x.release());
|
|
160
|
-
onDone();
|
|
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
|
+
};
|
|
161
276
|
};
|
|
162
277
|
}
|
|
163
278
|
}
|
|
@@ -181,7 +296,7 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
181
296
|
}
|
|
182
297
|
register.set(key, info);
|
|
183
298
|
const current = getter
|
|
184
|
-
? () => getter
|
|
299
|
+
? () => getter(parent, key)
|
|
185
300
|
: () => state[key];
|
|
186
301
|
function compute(initial) {
|
|
187
302
|
try {
|
|
@@ -239,7 +354,7 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
239
354
|
}
|
|
240
355
|
finally {
|
|
241
356
|
sub.commit();
|
|
242
|
-
for (const key in sub.
|
|
357
|
+
for (const key in sub.watch) {
|
|
243
358
|
const peer = register.get(key);
|
|
244
359
|
if (peer && peer.priority >= info.priority)
|
|
245
360
|
info.priority = peer.priority + 1;
|
|
@@ -259,7 +374,7 @@ function prepare(parent, key, source, setter, getter) {
|
|
|
259
374
|
enumerable: true
|
|
260
375
|
});
|
|
261
376
|
}
|
|
262
|
-
function ensure(on, keys) {
|
|
377
|
+
function ensure$1(on, keys) {
|
|
263
378
|
for (const key of keys) {
|
|
264
379
|
const desc = getOwnPropertyDescriptor(on.subject, key);
|
|
265
380
|
const getter = desc && desc.get;
|
|
@@ -282,6 +397,287 @@ function flush(on) {
|
|
|
282
397
|
KEYS.delete(on);
|
|
283
398
|
}
|
|
284
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
|
+
|
|
285
681
|
const Lifecycle = {
|
|
286
682
|
WILL_RENDER: "willRender",
|
|
287
683
|
WILL_UPDATE: "willUpdate",
|
|
@@ -289,7 +685,7 @@ const Lifecycle = {
|
|
|
289
685
|
WILL_UNMOUNT: "willUnmount",
|
|
290
686
|
DID_MOUNT: "didMount"
|
|
291
687
|
};
|
|
292
|
-
|
|
688
|
+
[
|
|
293
689
|
"didCreate",
|
|
294
690
|
"willDestroy",
|
|
295
691
|
...values(Lifecycle)
|
|
@@ -297,7 +693,7 @@ const lifecycleEvents = [
|
|
|
297
693
|
function lifecycle(prefix) {
|
|
298
694
|
const type = eventsFor(prefix);
|
|
299
695
|
return function useLifecycle(sub, tag) {
|
|
300
|
-
const emit =
|
|
696
|
+
const emit = React__default["default"].useMemo(() => {
|
|
301
697
|
const subject = sub.source;
|
|
302
698
|
const id = typeof tag == "function" ? tag(subject) : tag;
|
|
303
699
|
return (name) => {
|
|
@@ -309,7 +705,7 @@ function lifecycle(prefix) {
|
|
|
309
705
|
emit(sub.active
|
|
310
706
|
? Lifecycle.WILL_UPDATE
|
|
311
707
|
: Lifecycle.WILL_MOUNT);
|
|
312
|
-
|
|
708
|
+
React__default["default"].useLayoutEffect(() => {
|
|
313
709
|
sub.commit();
|
|
314
710
|
emit(Lifecycle.DID_MOUNT);
|
|
315
711
|
return () => {
|
|
@@ -323,210 +719,264 @@ function eventsFor(prefix) {
|
|
|
323
719
|
const map = new Map();
|
|
324
720
|
for (const name of values(Lifecycle)) {
|
|
325
721
|
const alias = prefix + name[0].toUpperCase() + name.slice(1);
|
|
326
|
-
lifecycleEvents.push(alias);
|
|
327
722
|
map.set(name, alias);
|
|
328
723
|
}
|
|
329
724
|
return (e) => map.get(e);
|
|
330
725
|
}
|
|
331
726
|
|
|
332
|
-
const
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
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];
|
|
338
734
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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;
|
|
741
|
+
}
|
|
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;
|
|
778
|
+
}
|
|
779
|
+
});
|
|
350
780
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
return placeholder;
|
|
781
|
+
return sub;
|
|
782
|
+
});
|
|
783
|
+
React__default["default"].useLayoutEffect(() => hook.commit(), []);
|
|
784
|
+
return hook.proxy;
|
|
356
785
|
}
|
|
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
|
-
|
|
385
|
-
|
|
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;
|
|
798
|
+
}
|
|
799
|
+
else
|
|
800
|
+
refresh();
|
|
801
|
+
};
|
|
802
|
+
if (value instanceof Promise) {
|
|
803
|
+
value.then(set);
|
|
804
|
+
value = undefined;
|
|
805
|
+
}
|
|
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;
|
|
386
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
|
+
};
|
|
387
837
|
});
|
|
388
|
-
|
|
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();
|
|
389
850
|
}
|
|
390
|
-
get
|
|
391
|
-
return
|
|
851
|
+
get local() {
|
|
852
|
+
return [
|
|
853
|
+
...new Set(getOwnPropertySymbols(this).map(symbol => this[symbol]))
|
|
854
|
+
];
|
|
392
855
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const { value } = desc;
|
|
399
|
-
const instruction = Pending.get(value);
|
|
400
|
-
if (instruction) {
|
|
401
|
-
Pending.delete(value);
|
|
402
|
-
delete subject[key];
|
|
403
|
-
instruction.call(this, key, this);
|
|
404
|
-
}
|
|
405
|
-
else if (typeof value !== "function" || /^[A-Z]/.test(key))
|
|
406
|
-
this.manage(key, value);
|
|
407
|
-
}
|
|
856
|
+
key(T) {
|
|
857
|
+
let key = this.table.get(T);
|
|
858
|
+
if (!key) {
|
|
859
|
+
key = Symbol(T.name);
|
|
860
|
+
this.table.set(T, key);
|
|
408
861
|
}
|
|
409
|
-
|
|
410
|
-
return this;
|
|
411
|
-
}
|
|
412
|
-
select(using) {
|
|
413
|
-
const keys = getOwnPropertyNames(this.state);
|
|
414
|
-
return using
|
|
415
|
-
? selectRecursive(using, keys.concat(lifecycleEvents))
|
|
416
|
-
: keys;
|
|
417
|
-
}
|
|
418
|
-
manage(key, initial, effect) {
|
|
419
|
-
const { state, subject } = this;
|
|
420
|
-
state[key] = initial;
|
|
421
|
-
defineProperty(subject, key, {
|
|
422
|
-
enumerable: true,
|
|
423
|
-
configurable: true,
|
|
424
|
-
get: () => state[key],
|
|
425
|
-
set: this.setter(key, effect)
|
|
426
|
-
});
|
|
862
|
+
return key;
|
|
427
863
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
return (value) => {
|
|
431
|
-
if (state[key] == value)
|
|
432
|
-
return;
|
|
433
|
-
if (handler)
|
|
434
|
-
switch (handler.call(subject, value)) {
|
|
435
|
-
case true:
|
|
436
|
-
this.update(key);
|
|
437
|
-
case false:
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
this.update(key, value);
|
|
441
|
-
};
|
|
864
|
+
get(T) {
|
|
865
|
+
return this[this.key(T)];
|
|
442
866
|
}
|
|
443
|
-
|
|
444
|
-
this
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
867
|
+
push(I) {
|
|
868
|
+
const next = create(this);
|
|
869
|
+
if (I instanceof Model || typeof I == "function")
|
|
870
|
+
next.register(I);
|
|
871
|
+
else
|
|
872
|
+
for (const i of values(I))
|
|
873
|
+
next.register(i);
|
|
874
|
+
return next;
|
|
448
875
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if (
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
setTimeout(() => this.emit(), 0);
|
|
456
|
-
this.frame.add(key);
|
|
457
|
-
for (const subscription of this.followers) {
|
|
458
|
-
const notify = subscription(key, this);
|
|
459
|
-
if (notify)
|
|
460
|
-
this.waiting.add(notify);
|
|
876
|
+
register(I) {
|
|
877
|
+
let writable = true;
|
|
878
|
+
let T;
|
|
879
|
+
if (I instanceof Model) {
|
|
880
|
+
T = I.constructor;
|
|
881
|
+
writable = false;
|
|
461
882
|
}
|
|
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;
|
|
462
898
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
this.frame.clear();
|
|
470
|
-
handle.forEach(callback => {
|
|
471
|
-
try {
|
|
472
|
-
callback(handled);
|
|
473
|
-
}
|
|
474
|
-
catch (e) { }
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
function keys(from, using) {
|
|
479
|
-
if (typeof using == "string")
|
|
480
|
-
return [using];
|
|
481
|
-
if (typeof using == "object") {
|
|
482
|
-
using = Array.from(using);
|
|
483
|
-
if (using.length === 0)
|
|
484
|
-
using = undefined;
|
|
485
|
-
else
|
|
486
|
-
return using;
|
|
899
|
+
pop() {
|
|
900
|
+
for (const key of getOwnPropertySymbols(this)) {
|
|
901
|
+
const entry = getOwnPropertyDescriptor(this, key);
|
|
902
|
+
if (entry.writable)
|
|
903
|
+
entry.value.destroy();
|
|
904
|
+
}
|
|
487
905
|
}
|
|
488
|
-
return from.select(using);
|
|
489
906
|
}
|
|
490
907
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
|
|
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.`
|
|
912
|
+
});
|
|
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;
|
|
920
|
+
}
|
|
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;
|
|
525
954
|
};
|
|
526
|
-
},
|
|
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 {};
|
|
964
|
+
});
|
|
965
|
+
if (hook.commit)
|
|
966
|
+
React__default["default"].useLayoutEffect(() => hook.commit(), []);
|
|
967
|
+
return props.render(hook.proxy);
|
|
968
|
+
}
|
|
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);
|
|
527
977
|
}
|
|
528
978
|
|
|
529
|
-
const Oops$
|
|
979
|
+
const Oops$4 = issues({
|
|
530
980
|
CantAttachGlobal: (parent, child) => `Singleton '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
531
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.`
|
|
532
982
|
});
|
|
@@ -534,14 +984,16 @@ const PendingContext = new WeakMap();
|
|
|
534
984
|
const ContextWasUsed = new WeakMap();
|
|
535
985
|
function tap(type, argument) {
|
|
536
986
|
return child(function tap(key) {
|
|
537
|
-
return
|
|
987
|
+
return {
|
|
988
|
+
get: pendingAccess(this.subject, type, key, argument)
|
|
989
|
+
};
|
|
538
990
|
});
|
|
539
991
|
}
|
|
540
992
|
function pendingAccess(from, type, key, argument) {
|
|
541
|
-
if ("
|
|
542
|
-
return () => type.
|
|
543
|
-
if ("
|
|
544
|
-
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);
|
|
545
997
|
let instance;
|
|
546
998
|
getPending(from).push(context => {
|
|
547
999
|
instance = context.get(type);
|
|
@@ -550,7 +1002,7 @@ function pendingAccess(from, type, key, argument) {
|
|
|
550
1002
|
instance = undefined;
|
|
551
1003
|
}
|
|
552
1004
|
else if (!instance && argument)
|
|
553
|
-
throw Oops$
|
|
1005
|
+
throw Oops$4.AmbientRequired(type.name, from, key);
|
|
554
1006
|
});
|
|
555
1007
|
return () => instance;
|
|
556
1008
|
}
|
|
@@ -576,7 +1028,7 @@ function getPending(subject) {
|
|
|
576
1028
|
return pending;
|
|
577
1029
|
}
|
|
578
1030
|
|
|
579
|
-
const Oops$
|
|
1031
|
+
const Oops$3 = issues({
|
|
580
1032
|
DuplicateAction: (key) => `Invoked action ${key} but one is already active.`,
|
|
581
1033
|
BadComputedSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
582
1034
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`
|
|
@@ -593,7 +1045,7 @@ function ref(arg) {
|
|
|
593
1045
|
return apply(function ref(key) {
|
|
594
1046
|
let value = {};
|
|
595
1047
|
if (typeof arg == "object") {
|
|
596
|
-
const source =
|
|
1048
|
+
const source = getController(arg);
|
|
597
1049
|
for (const key in source.state)
|
|
598
1050
|
defineLazy(value, key, createRef.bind(source, key));
|
|
599
1051
|
}
|
|
@@ -607,7 +1059,7 @@ function act(task) {
|
|
|
607
1059
|
let pending = false;
|
|
608
1060
|
const invoke = (...args) => {
|
|
609
1061
|
if (pending)
|
|
610
|
-
return Promise.reject(Oops$
|
|
1062
|
+
return Promise.reject(Oops$3.DuplicateAction(key));
|
|
611
1063
|
pending = true;
|
|
612
1064
|
this.update(key);
|
|
613
1065
|
return new Promise(res => {
|
|
@@ -628,16 +1080,19 @@ function act(task) {
|
|
|
628
1080
|
};
|
|
629
1081
|
});
|
|
630
1082
|
}
|
|
631
|
-
function from(source, setter,
|
|
1083
|
+
function from(source, setter, argument) {
|
|
632
1084
|
return apply(function from(key) {
|
|
633
|
-
const { subject } = this;
|
|
634
1085
|
let getSource;
|
|
1086
|
+
const { subject } = this;
|
|
1087
|
+
const getter = argument === true
|
|
1088
|
+
? pendingValue
|
|
1089
|
+
: argument || undefined;
|
|
635
1090
|
// Easy mistake, using a peer, will always be unresolved.
|
|
636
1091
|
if (typeof source == "symbol")
|
|
637
|
-
throw Oops$
|
|
1092
|
+
throw Oops$3.PeerNotAllowed(subject, key);
|
|
638
1093
|
// replace source controller in-case different
|
|
639
1094
|
if (typeof source == "object")
|
|
640
|
-
getSource = () =>
|
|
1095
|
+
getSource = () => getController(source);
|
|
641
1096
|
// specifically an arrow function (getter factory)
|
|
642
1097
|
else if (!source.prototype) {
|
|
643
1098
|
setter = source.call(subject, key);
|
|
@@ -646,22 +1101,24 @@ function from(source, setter, getter) {
|
|
|
646
1101
|
// is a peer Model (constructor)
|
|
647
1102
|
else if (Model.isTypeof(source))
|
|
648
1103
|
getSource = pendingAccess(subject, source, key, true);
|
|
649
|
-
// Regular function is
|
|
1104
|
+
// Regular function is too ambiguous so not allowed.
|
|
650
1105
|
else
|
|
651
|
-
throw Oops$
|
|
1106
|
+
throw Oops$3.BadComputedSource(subject, key, source);
|
|
652
1107
|
prepare(this, key, getSource, setter, getter);
|
|
653
1108
|
});
|
|
654
1109
|
}
|
|
655
1110
|
|
|
656
|
-
const Oops$
|
|
1111
|
+
const Oops$2 = issues({
|
|
657
1112
|
ValueNotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
658
1113
|
});
|
|
1114
|
+
/* deprecated - ignore coverage */
|
|
1115
|
+
/* istanbul ignore next */
|
|
659
1116
|
function pending(source, compute) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1117
|
+
if (source === undefined)
|
|
1118
|
+
return set();
|
|
1119
|
+
if (typeof source == "function" && !source.prototype)
|
|
1120
|
+
return set(source);
|
|
1121
|
+
return from(source, compute, true);
|
|
665
1122
|
}
|
|
666
1123
|
/**
|
|
667
1124
|
* Get value, suspend instead if undefined.
|
|
@@ -675,442 +1132,140 @@ function pendingValue(via, key) {
|
|
|
675
1132
|
throw suspend(via, key);
|
|
676
1133
|
return value;
|
|
677
1134
|
}
|
|
678
|
-
function
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
function getter(_value, key) {
|
|
700
|
-
return pendingValue(manage(this), key);
|
|
701
|
-
}
|
|
702
|
-
return from(source, compute, getter);
|
|
703
|
-
}
|
|
704
|
-
function suspendForValue() {
|
|
705
|
-
return apply(function pending(key) {
|
|
706
|
-
this.state[key] = undefined;
|
|
707
|
-
return {
|
|
708
|
-
set: this.setter(key),
|
|
709
|
-
get: () => pendingValue(this, key)
|
|
710
|
-
};
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
function suspendForAsync(source) {
|
|
714
|
-
return apply(function suspense(key) {
|
|
715
|
-
const subject = this.subject;
|
|
716
|
-
let waiting = true;
|
|
717
|
-
let value;
|
|
718
|
-
let error;
|
|
719
|
-
return () => {
|
|
720
|
-
if (error)
|
|
721
|
-
throw error;
|
|
722
|
-
if (!waiting)
|
|
723
|
-
return value;
|
|
724
|
-
const issue = Oops$4.ValueNotReady(subject, key);
|
|
725
|
-
let suspend = source
|
|
726
|
-
.call(subject, key)
|
|
1135
|
+
function pendingFactory(via, key, fn) {
|
|
1136
|
+
const { subject, state } = via;
|
|
1137
|
+
let waiting;
|
|
1138
|
+
let error;
|
|
1139
|
+
return () => {
|
|
1140
|
+
if (waiting)
|
|
1141
|
+
throw waiting;
|
|
1142
|
+
if (error)
|
|
1143
|
+
throw error;
|
|
1144
|
+
if (key in state)
|
|
1145
|
+
return state[key];
|
|
1146
|
+
let output;
|
|
1147
|
+
try {
|
|
1148
|
+
output = fn.call(subject, key, subject);
|
|
1149
|
+
}
|
|
1150
|
+
catch (err) {
|
|
1151
|
+
throw error = err;
|
|
1152
|
+
}
|
|
1153
|
+
if (output instanceof Promise) {
|
|
1154
|
+
const issue = Oops$2.ValueNotReady(subject, key);
|
|
1155
|
+
output
|
|
727
1156
|
.catch(err => error = err)
|
|
728
|
-
.then(out =>
|
|
729
|
-
.finally(() => waiting =
|
|
730
|
-
throw Object.assign(
|
|
1157
|
+
.then(out => state[key] = out)
|
|
1158
|
+
.finally(() => waiting = undefined);
|
|
1159
|
+
throw waiting = Object.assign(output, {
|
|
731
1160
|
message: issue.message,
|
|
732
1161
|
stack: issue.stack
|
|
733
1162
|
});
|
|
734
|
-
};
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
function use$1(init) {
|
|
739
|
-
const [state, update] = react.useState(() => [
|
|
740
|
-
init(() => update(state.concat()))
|
|
741
|
-
]);
|
|
742
|
-
return state[0];
|
|
743
|
-
}
|
|
744
|
-
function useLazy(Type, callback) {
|
|
745
|
-
const instance = react.useMemo(() => {
|
|
746
|
-
const instance = Type.create();
|
|
747
|
-
if (callback)
|
|
748
|
-
callback(instance);
|
|
749
|
-
return instance;
|
|
750
|
-
}, []);
|
|
751
|
-
react.useLayoutEffect(() => () => instance.destroy(), []);
|
|
752
|
-
return instance;
|
|
753
|
-
}
|
|
754
|
-
function useWatcher(target, focus, expected) {
|
|
755
|
-
const hook = use$1(refresh => {
|
|
756
|
-
const sub = new Subscriber(target, () => refresh);
|
|
757
|
-
if (focus) {
|
|
758
|
-
const source = sub.proxy;
|
|
759
|
-
defineProperty(sub, "proxy", {
|
|
760
|
-
get() {
|
|
761
|
-
const value = source[focus];
|
|
762
|
-
if (value === undefined && expected)
|
|
763
|
-
throw suspend(sub.parent, focus);
|
|
764
|
-
return value;
|
|
765
|
-
}
|
|
766
|
-
});
|
|
767
1163
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
}
|
|
773
|
-
function useComputed(target, compute, expected) {
|
|
774
|
-
const hook = use$1(refresh => {
|
|
775
|
-
const sub = new Subscriber(target, () => update);
|
|
776
|
-
const { proxy } = sub;
|
|
777
|
-
let value;
|
|
778
|
-
let retry;
|
|
779
|
-
const update = () => {
|
|
780
|
-
const next = compute.call(proxy, proxy);
|
|
781
|
-
if (value == next)
|
|
782
|
-
return;
|
|
783
|
-
value = next;
|
|
784
|
-
if (retry) {
|
|
785
|
-
retry();
|
|
786
|
-
retry = undefined;
|
|
787
|
-
}
|
|
788
|
-
else
|
|
789
|
-
refresh();
|
|
790
|
-
};
|
|
791
|
-
const access = () => {
|
|
792
|
-
if (value === undefined && expected)
|
|
793
|
-
throw new Promise(res => {
|
|
794
|
-
retry = res;
|
|
795
|
-
});
|
|
796
|
-
return value;
|
|
797
|
-
};
|
|
798
|
-
value = compute.call(proxy, proxy);
|
|
799
|
-
sub.commit();
|
|
800
|
-
defineProperty(sub, "proxy", { get: access });
|
|
801
|
-
return sub;
|
|
802
|
-
});
|
|
803
|
-
react.useLayoutEffect(() => hook.release, []);
|
|
804
|
-
return hook.proxy;
|
|
1164
|
+
else {
|
|
1165
|
+
return state[key] = output;
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
805
1168
|
}
|
|
806
|
-
function
|
|
807
|
-
const
|
|
808
|
-
|
|
809
|
-
const
|
|
810
|
-
|
|
811
|
-
const release = control.addListener((key) => {
|
|
812
|
-
if (key == Lifecycle.WILL_UNMOUNT)
|
|
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)
|
|
813
1174
|
return () => {
|
|
814
|
-
|
|
815
|
-
|
|
1175
|
+
if (source.state[key] !== undefined) {
|
|
1176
|
+
release();
|
|
1177
|
+
resolve();
|
|
1178
|
+
}
|
|
816
1179
|
};
|
|
817
1180
|
});
|
|
818
|
-
if (callback)
|
|
819
|
-
callback(instance);
|
|
820
|
-
return sub;
|
|
821
1181
|
});
|
|
822
|
-
return
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
829
|
-
get local() {
|
|
830
|
-
return getOwnPropertySymbols(this).map((symbol) => this[symbol]);
|
|
831
|
-
}
|
|
832
|
-
key(T) {
|
|
833
|
-
let key = this.table.get(T);
|
|
834
|
-
if (!key) {
|
|
835
|
-
key = Symbol(T.name);
|
|
836
|
-
this.table.set(T, key);
|
|
837
|
-
}
|
|
838
|
-
return key;
|
|
839
|
-
}
|
|
840
|
-
get(T) {
|
|
841
|
-
return this[this.key(T)];
|
|
842
|
-
}
|
|
843
|
-
push(I) {
|
|
844
|
-
const next = create(this);
|
|
845
|
-
if (I instanceof Model || typeof I == "function")
|
|
846
|
-
next.register(I);
|
|
847
|
-
else
|
|
848
|
-
for (const i of values(I))
|
|
849
|
-
next.register(i);
|
|
850
|
-
return next;
|
|
851
|
-
}
|
|
852
|
-
register(I) {
|
|
853
|
-
let writable = true;
|
|
854
|
-
let T;
|
|
855
|
-
if (I instanceof Model) {
|
|
856
|
-
T = I.constructor;
|
|
857
|
-
writable = false;
|
|
858
|
-
}
|
|
859
|
-
else {
|
|
860
|
-
T = I;
|
|
861
|
-
I = I.create();
|
|
862
|
-
}
|
|
863
|
-
do {
|
|
864
|
-
defineProperty(this, this.key(T), {
|
|
865
|
-
value: I, writable
|
|
866
|
-
});
|
|
867
|
-
T = getPrototypeOf(T);
|
|
868
|
-
} while (T !== Model);
|
|
869
|
-
return I;
|
|
870
|
-
}
|
|
871
|
-
pop() {
|
|
872
|
-
for (const key of getOwnPropertySymbols(this)) {
|
|
873
|
-
const entry = getOwnPropertyDescriptor(this, key);
|
|
874
|
-
if (entry.writable)
|
|
875
|
-
entry.value.destroy();
|
|
876
|
-
}
|
|
877
|
-
}
|
|
1182
|
+
return Object.assign(promise, {
|
|
1183
|
+
toString: () => String(error),
|
|
1184
|
+
name: "Suspense",
|
|
1185
|
+
message: error.message,
|
|
1186
|
+
stack: error.stack
|
|
1187
|
+
});
|
|
878
1188
|
}
|
|
879
1189
|
|
|
880
|
-
const Oops$
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
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.`
|
|
884
1194
|
});
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
}
|
|
893
|
-
function Consumer(props) {
|
|
894
|
-
const { get, has, children, of: Control } = props;
|
|
895
|
-
if (typeof children == "function")
|
|
896
|
-
return children(Control.tap());
|
|
897
|
-
const callback = has || get;
|
|
898
|
-
if (typeof callback == "function")
|
|
899
|
-
callback(Control.get(!!has));
|
|
900
|
-
else
|
|
901
|
-
throw Oops$3.BadConsumerProps();
|
|
902
|
-
return null;
|
|
903
|
-
}
|
|
904
|
-
function useNewContext(from, inject) {
|
|
905
|
-
return react.useMemo(() => {
|
|
906
|
-
if (!inject)
|
|
907
|
-
throw Oops$3.NoProviderType();
|
|
908
|
-
const context = from.push(inject);
|
|
909
|
-
for (const instance of context.local)
|
|
910
|
-
for (const apply of getPending(instance))
|
|
911
|
-
apply(context);
|
|
912
|
-
return context;
|
|
913
|
-
}, []);
|
|
914
|
-
}
|
|
915
|
-
function useAppliedProps(within, props) {
|
|
916
|
-
const update = react.useMemo(() => {
|
|
917
|
-
const targets = within.local;
|
|
918
|
-
return function integrate(props) {
|
|
919
|
-
for (const [key, value] of entries(props))
|
|
920
|
-
if (key != "of" && key != "children")
|
|
921
|
-
for (const into of targets)
|
|
922
|
-
if (key in into)
|
|
923
|
-
into[key] = value;
|
|
924
|
-
};
|
|
925
|
-
}, []);
|
|
926
|
-
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
|
+
});
|
|
927
1203
|
}
|
|
928
|
-
function
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
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 };
|
|
934
1236
|
});
|
|
935
|
-
if (hook.commit)
|
|
936
|
-
react.useLayoutEffect(() => hook.commit(), []);
|
|
937
|
-
return props.render(hook.proxy);
|
|
938
1237
|
}
|
|
939
|
-
function
|
|
940
|
-
|
|
941
|
-
const current = useLookup();
|
|
942
|
-
const context = useNewContext(current, props.of);
|
|
943
|
-
useAppliedProps(context, props);
|
|
944
|
-
react.useLayoutEffect(() => () => context.pop(), []);
|
|
945
|
-
return react.createElement(LookupContext.Provider, { value: context }, typeof render == "function"
|
|
946
|
-
? react.createElement(RenderFunction, { context, render })
|
|
947
|
-
: render);
|
|
1238
|
+
function on(initial, onUpdate) {
|
|
1239
|
+
return set(initial && (() => initial), onUpdate);
|
|
948
1240
|
}
|
|
949
1241
|
|
|
950
|
-
|
|
951
|
-
StrictUpdate: (expected) => `Strict update() did ${expected ? "not " : ""}find pending updates.`,
|
|
952
|
-
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
953
|
-
});
|
|
954
|
-
const useElementLifecycle = lifecycle("element");
|
|
955
|
-
const useComponentLifecycle = lifecycle("component");
|
|
956
|
-
class Model {
|
|
957
|
-
constructor() {
|
|
958
|
-
const control = Controller.setup(this);
|
|
959
|
-
define(this, "get", this);
|
|
960
|
-
define(this, "set", this);
|
|
961
|
-
defer(control, "on");
|
|
962
|
-
defer(control, "effect");
|
|
963
|
-
control.waiting.add(() => {
|
|
964
|
-
delete this.on;
|
|
965
|
-
delete this.effect;
|
|
966
|
-
});
|
|
967
|
-
}
|
|
1242
|
+
class MVC extends Model {
|
|
968
1243
|
tap(path, expect) {
|
|
969
|
-
|
|
970
|
-
return useComputed(this, path, expect);
|
|
971
|
-
const proxy = useWatcher(this, path, expect);
|
|
972
|
-
this.update("willRender", true);
|
|
973
|
-
return proxy;
|
|
1244
|
+
return useTap(this, path, expect);
|
|
974
1245
|
}
|
|
975
1246
|
tag(id) {
|
|
976
|
-
|
|
977
|
-
return new Subscriber(this, () => refresh);
|
|
978
|
-
});
|
|
979
|
-
useElementLifecycle(hook, id || 0);
|
|
980
|
-
return hook.proxy;
|
|
1247
|
+
return useTag(this, id);
|
|
981
1248
|
}
|
|
982
1249
|
use(callback) {
|
|
983
|
-
|
|
984
|
-
if (callback)
|
|
985
|
-
callback(this);
|
|
986
|
-
return new Subscriber(this, () => refresh);
|
|
987
|
-
});
|
|
988
|
-
useComponentLifecycle(hook);
|
|
989
|
-
return hook.proxy;
|
|
990
|
-
}
|
|
991
|
-
on(subset, handler, squash, once) {
|
|
992
|
-
const control = manage(this);
|
|
993
|
-
const request = keys(control, subset);
|
|
994
|
-
const callback = squash
|
|
995
|
-
? handler.bind(this)
|
|
996
|
-
: frame => frame
|
|
997
|
-
.filter(k => request.includes(k))
|
|
998
|
-
.forEach(k => handler.call(this, control.state[k], k));
|
|
999
|
-
const trigger = once
|
|
1000
|
-
? frame => { remove(); callback(frame); }
|
|
1001
|
-
: callback;
|
|
1002
|
-
ensure(control, request);
|
|
1003
|
-
const remove = control.addListener(key => {
|
|
1004
|
-
if (request.includes(key))
|
|
1005
|
-
return trigger;
|
|
1006
|
-
});
|
|
1007
|
-
return remove;
|
|
1008
|
-
}
|
|
1009
|
-
once(select, callback, squash) {
|
|
1010
|
-
if (callback)
|
|
1011
|
-
return this.on(select, callback, squash, true);
|
|
1012
|
-
else
|
|
1013
|
-
return new Promise(resolve => {
|
|
1014
|
-
this.on(select, resolve, true, true);
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
effect(callback, select) {
|
|
1018
|
-
const control = manage(this);
|
|
1019
|
-
let target = this;
|
|
1020
|
-
const effect = createEffect(callback);
|
|
1021
|
-
const invoke = () => effect.call(target, target);
|
|
1022
|
-
if (select) {
|
|
1023
|
-
invoke();
|
|
1024
|
-
return this.on(select, invoke, true);
|
|
1025
|
-
}
|
|
1026
|
-
else {
|
|
1027
|
-
const sub = new Subscriber(control, () => invoke);
|
|
1028
|
-
target = sub.proxy;
|
|
1029
|
-
invoke();
|
|
1030
|
-
return sub.commit();
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
import(from, subset) {
|
|
1034
|
-
for (const key of keys(manage(this), subset))
|
|
1035
|
-
if (key in from)
|
|
1036
|
-
this[key] = from[key];
|
|
1037
|
-
}
|
|
1038
|
-
export(subset) {
|
|
1039
|
-
const control = manage(this);
|
|
1040
|
-
const output = {};
|
|
1041
|
-
for (const key of keys(control, subset))
|
|
1042
|
-
output[key] = control.state[key];
|
|
1043
|
-
return output;
|
|
1044
|
-
}
|
|
1045
|
-
update(arg, tag) {
|
|
1046
|
-
const control = manage(this);
|
|
1047
|
-
if (typeof arg == "function")
|
|
1048
|
-
arg = select(this, arg);
|
|
1049
|
-
if (typeof arg == "boolean") {
|
|
1050
|
-
if (!control.pending === arg)
|
|
1051
|
-
return Promise.reject(Oops$2.StrictUpdate(arg));
|
|
1052
|
-
}
|
|
1053
|
-
else if (arg) {
|
|
1054
|
-
control.update(arg);
|
|
1055
|
-
if (1 in arguments && arg in this) {
|
|
1056
|
-
const method = this[arg];
|
|
1057
|
-
if (typeof method == "function")
|
|
1058
|
-
if (typeof tag != "boolean")
|
|
1059
|
-
method.call(this, tag);
|
|
1060
|
-
else if (tag)
|
|
1061
|
-
method.call(this);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
return {
|
|
1065
|
-
then(callback) {
|
|
1066
|
-
if (callback)
|
|
1067
|
-
if (control.pending)
|
|
1068
|
-
control.waiting.add(callback);
|
|
1069
|
-
else
|
|
1070
|
-
callback(false);
|
|
1071
|
-
else
|
|
1072
|
-
throw Oops$2.NoChaining();
|
|
1073
|
-
}
|
|
1074
|
-
};
|
|
1075
|
-
}
|
|
1076
|
-
destroy() {
|
|
1077
|
-
this.update("willDestroy", true);
|
|
1078
|
-
}
|
|
1079
|
-
toString() {
|
|
1080
|
-
return this.constructor.name;
|
|
1081
|
-
}
|
|
1082
|
-
static create(...args) {
|
|
1083
|
-
const instance = new this(...args);
|
|
1084
|
-
manage(instance);
|
|
1085
|
-
return instance;
|
|
1250
|
+
return useNew(this, callback);
|
|
1086
1251
|
}
|
|
1087
1252
|
static new(callback) {
|
|
1088
|
-
|
|
1089
|
-
instance.update("willRender", true);
|
|
1090
|
-
return instance;
|
|
1091
|
-
}
|
|
1092
|
-
static find(strict) {
|
|
1093
|
-
return useFromContext(this, strict);
|
|
1253
|
+
return usePassive(this, callback);
|
|
1094
1254
|
}
|
|
1095
1255
|
static get(key) {
|
|
1096
|
-
const instance = this
|
|
1097
|
-
return (typeof key == "
|
|
1098
|
-
key
|
|
1099
|
-
|
|
1100
|
-
instance[key] :
|
|
1101
|
-
instance);
|
|
1256
|
+
const instance = useContext(this, key !== false);
|
|
1257
|
+
return (typeof key == "string" ?
|
|
1258
|
+
instance[key] :
|
|
1259
|
+
instance);
|
|
1102
1260
|
}
|
|
1103
1261
|
static tap(key, expect) {
|
|
1104
|
-
return this.
|
|
1262
|
+
return this.get().tap(key, expect);
|
|
1105
1263
|
}
|
|
1106
1264
|
static tag(id) {
|
|
1107
|
-
return this.
|
|
1265
|
+
return this.get().tag(id);
|
|
1108
1266
|
}
|
|
1109
1267
|
static use(callback) {
|
|
1110
|
-
|
|
1111
|
-
useComponentLifecycle(instance[LOCAL]);
|
|
1112
|
-
usePeerContext(instance.get);
|
|
1113
|
-
return instance;
|
|
1268
|
+
return useModel(this, callback);
|
|
1114
1269
|
}
|
|
1115
1270
|
static uses(props, only) {
|
|
1116
1271
|
return this.use(instance => {
|
|
@@ -1122,131 +1277,11 @@ class Model {
|
|
|
1122
1277
|
instance.import(props, only);
|
|
1123
1278
|
return instance;
|
|
1124
1279
|
}
|
|
1125
|
-
static meta(path) {
|
|
1280
|
+
static meta(path, expect) {
|
|
1126
1281
|
return typeof path == "function"
|
|
1127
|
-
? useComputed(this, path)
|
|
1128
|
-
:
|
|
1282
|
+
? useComputed(this, path, expect)
|
|
1283
|
+
: useActive(this, path, expect);
|
|
1129
1284
|
}
|
|
1130
|
-
static isTypeof(maybe) {
|
|
1131
|
-
return (typeof maybe == "function" &&
|
|
1132
|
-
maybe.prototype instanceof this);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
Model.CONTROL = CONTROL;
|
|
1136
|
-
Model.STATE = STATE;
|
|
1137
|
-
Model.LOCAL = LOCAL;
|
|
1138
|
-
Model.WHY = UPDATE;
|
|
1139
|
-
defineLazy(Model, CONTROL, function () {
|
|
1140
|
-
return new Controller(this).start();
|
|
1141
|
-
});
|
|
1142
|
-
function defer(on, method) {
|
|
1143
|
-
const { subject, waiting } = on;
|
|
1144
|
-
const real = subject[method];
|
|
1145
|
-
subject[method] = (...args) => {
|
|
1146
|
-
let done;
|
|
1147
|
-
waiting.add(() => {
|
|
1148
|
-
done = real.apply(subject, args);
|
|
1149
|
-
});
|
|
1150
|
-
return () => done();
|
|
1151
|
-
};
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
const Parent = new WeakMap();
|
|
1155
|
-
const Oops$1 = issues({
|
|
1156
|
-
ParentRequired: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1157
|
-
UnexpectedParent: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1158
|
-
UndefinedNotAllowed: (key) => `Child property ${key} may not be undefined.`,
|
|
1159
|
-
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1160
|
-
IsReadOnly: (owner, key) => `${owner}.${key} is set to read-only, but tried to reassign assign.`,
|
|
1161
|
-
MustBeDefined: (owner, key) => `${owner}.${key} must have initial value, as a read-only property.`
|
|
1162
|
-
});
|
|
1163
|
-
function bootstrap(object) {
|
|
1164
|
-
const breakdown = getOwnPropertyDescriptors(object);
|
|
1165
|
-
const control = new Model();
|
|
1166
|
-
for (const key in breakdown)
|
|
1167
|
-
defineProperty(control, key, breakdown[key]);
|
|
1168
|
-
return control;
|
|
1169
|
-
}
|
|
1170
|
-
function use(input, argument) {
|
|
1171
|
-
return child(function use(key) {
|
|
1172
|
-
const { subject } = this;
|
|
1173
|
-
// `true` => readonly
|
|
1174
|
-
// `false` => writable, may be undefined
|
|
1175
|
-
// `undefined` => writable (default)
|
|
1176
|
-
let mode = argument;
|
|
1177
|
-
let current;
|
|
1178
|
-
const onUpdate = (next, initial) => {
|
|
1179
|
-
if (mode === true && !initial)
|
|
1180
|
-
throw Oops$1.IsReadOnly(subject, key);
|
|
1181
|
-
if (next) {
|
|
1182
|
-
current = next instanceof Model
|
|
1183
|
-
? next : bootstrap(next);
|
|
1184
|
-
Parent.set(current, subject);
|
|
1185
|
-
manage(current);
|
|
1186
|
-
}
|
|
1187
|
-
else if (mode === undefined)
|
|
1188
|
-
throw Oops$1.UndefinedNotAllowed(key);
|
|
1189
|
-
else
|
|
1190
|
-
current = undefined;
|
|
1191
|
-
if (typeof argument == "function")
|
|
1192
|
-
return argument(current);
|
|
1193
|
-
};
|
|
1194
|
-
if (input) {
|
|
1195
|
-
current =
|
|
1196
|
-
Model.isTypeof(input) ? new input() :
|
|
1197
|
-
input instanceof Model ? input :
|
|
1198
|
-
typeof input === "function" ? input() :
|
|
1199
|
-
typeof input === "object" ? bootstrap(input) :
|
|
1200
|
-
Oops$1.BadArgument(typeof input).throw();
|
|
1201
|
-
if (current)
|
|
1202
|
-
mode = onUpdate(current, true) || mode;
|
|
1203
|
-
else if (mode == true)
|
|
1204
|
-
throw Oops$1.MustBeDefined(subject, key);
|
|
1205
|
-
}
|
|
1206
|
-
else
|
|
1207
|
-
mode = false;
|
|
1208
|
-
this.manage(key, current, onUpdate);
|
|
1209
|
-
return () => current;
|
|
1210
|
-
});
|
|
1211
|
-
}
|
|
1212
|
-
function parent(Expects, required) {
|
|
1213
|
-
return apply(function parent() {
|
|
1214
|
-
const child = this.subject;
|
|
1215
|
-
const expected = Expects.name;
|
|
1216
|
-
const value = Parent.get(this.subject);
|
|
1217
|
-
if (!value) {
|
|
1218
|
-
if (required)
|
|
1219
|
-
throw Oops$1.ParentRequired(expected, child);
|
|
1220
|
-
}
|
|
1221
|
-
else if (!(value instanceof Expects))
|
|
1222
|
-
throw Oops$1.UnexpectedParent(expected, child, value);
|
|
1223
|
-
return { value };
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
function on(initial, cb) {
|
|
1228
|
-
return apply(function on(key) {
|
|
1229
|
-
this.manage(key, initial, cb && createValueEffect(cb));
|
|
1230
|
-
});
|
|
1231
|
-
}
|
|
1232
|
-
function memo(factory, defer) {
|
|
1233
|
-
return apply(function memo(key) {
|
|
1234
|
-
const source = this.subject;
|
|
1235
|
-
const get = () => factory.call(source);
|
|
1236
|
-
if (defer)
|
|
1237
|
-
defineLazy(source, key, get);
|
|
1238
|
-
else
|
|
1239
|
-
define(source, key, get());
|
|
1240
|
-
});
|
|
1241
|
-
}
|
|
1242
|
-
function lazy(value) {
|
|
1243
|
-
return apply(function lazy(key) {
|
|
1244
|
-
const source = this.subject;
|
|
1245
|
-
source[key] = value;
|
|
1246
|
-
defineProperty(this.state, key, {
|
|
1247
|
-
get: () => source[key]
|
|
1248
|
-
});
|
|
1249
|
-
});
|
|
1250
1285
|
}
|
|
1251
1286
|
|
|
1252
1287
|
const Oops = issues({
|
|
@@ -1254,35 +1289,32 @@ const Oops = issues({
|
|
|
1254
1289
|
GlobalExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
|
|
1255
1290
|
});
|
|
1256
1291
|
const Active = new WeakMap();
|
|
1257
|
-
class Singleton extends
|
|
1258
|
-
static get current() {
|
|
1259
|
-
return Active.get(this);
|
|
1260
|
-
}
|
|
1292
|
+
class Singleton extends MVC {
|
|
1261
1293
|
static create(...args) {
|
|
1262
1294
|
const Type = this;
|
|
1263
1295
|
if (Active.has(Type))
|
|
1264
1296
|
throw Oops.GlobalExists(this.name);
|
|
1265
|
-
|
|
1297
|
+
const instance = super.create(...args);
|
|
1266
1298
|
Active.set(Type, instance);
|
|
1267
1299
|
return instance;
|
|
1268
1300
|
}
|
|
1269
|
-
static
|
|
1270
|
-
const instance = this
|
|
1301
|
+
static set(updates) {
|
|
1302
|
+
const instance = Active.get(this) || this.create();
|
|
1271
1303
|
instance.import(updates);
|
|
1272
1304
|
return instance.update();
|
|
1273
1305
|
}
|
|
1274
|
-
static
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
static find(strict) {
|
|
1278
|
-
const instance = this.current;
|
|
1279
|
-
if (!instance && strict)
|
|
1306
|
+
static get(arg) {
|
|
1307
|
+
const instance = Active.get(this);
|
|
1308
|
+
if (!instance && arg !== false)
|
|
1280
1309
|
throw Oops.GlobalDoesNotExist(this.name);
|
|
1281
|
-
return
|
|
1310
|
+
return (typeof arg == "string" ?
|
|
1311
|
+
instance[arg] :
|
|
1312
|
+
instance);
|
|
1282
1313
|
}
|
|
1283
1314
|
static reset() {
|
|
1284
|
-
|
|
1285
|
-
|
|
1315
|
+
const current = Active.get(this);
|
|
1316
|
+
if (current)
|
|
1317
|
+
current.destroy();
|
|
1286
1318
|
}
|
|
1287
1319
|
destroy() {
|
|
1288
1320
|
super.destroy();
|
|
@@ -1291,20 +1323,21 @@ class Singleton extends Model {
|
|
|
1291
1323
|
}
|
|
1292
1324
|
|
|
1293
1325
|
exports.Consumer = Consumer;
|
|
1294
|
-
exports.Model =
|
|
1326
|
+
exports.Model = MVC;
|
|
1295
1327
|
exports.Provider = Provider;
|
|
1296
1328
|
exports.Singleton = Singleton;
|
|
1297
1329
|
exports.act = act;
|
|
1298
1330
|
exports.apply = apply;
|
|
1299
1331
|
exports.child = child;
|
|
1300
|
-
exports["default"] =
|
|
1332
|
+
exports["default"] = MVC;
|
|
1301
1333
|
exports.from = from;
|
|
1302
1334
|
exports.lazy = lazy;
|
|
1303
|
-
exports.memo =
|
|
1335
|
+
exports.memo = set;
|
|
1304
1336
|
exports.on = on;
|
|
1305
1337
|
exports.parent = parent;
|
|
1306
1338
|
exports.pending = pending;
|
|
1307
1339
|
exports.ref = ref;
|
|
1340
|
+
exports.set = set;
|
|
1308
1341
|
exports.tap = tap;
|
|
1309
|
-
exports.use = use;
|
|
1342
|
+
exports.use = use$1;
|
|
1310
1343
|
//# sourceMappingURL=index.js.map
|