@expressive/mvc 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +192 -283
- package/lib/index.esm.js +620 -811
- package/lib/index.js +620 -814
- package/package.json +1 -11
package/lib/index.js
CHANGED
|
@@ -2,10 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
|
|
20
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
21
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
9
28
|
}
|
|
10
29
|
|
|
11
30
|
class Issue extends Error {
|
|
@@ -25,89 +44,27 @@ function issues(register) {
|
|
|
25
44
|
return Library;
|
|
26
45
|
}
|
|
27
46
|
|
|
28
|
-
const
|
|
29
|
-
class Subscriber {
|
|
30
|
-
constructor(parent, onUpdate) {
|
|
31
|
-
this.onUpdate = onUpdate;
|
|
32
|
-
this.active = false;
|
|
33
|
-
this.dependant = new Set();
|
|
34
|
-
this.watch = new Map();
|
|
35
|
-
if (!(parent instanceof Control))
|
|
36
|
-
parent = Control.for(parent);
|
|
37
|
-
const reset = () => this.latest = undefined;
|
|
38
|
-
const proxy = create(parent.subject);
|
|
39
|
-
REGISTER$1.set(proxy, this);
|
|
40
|
-
defineProperty(this, "proxy", {
|
|
41
|
-
configurable: true,
|
|
42
|
-
get() {
|
|
43
|
-
setTimeout(reset, 0);
|
|
44
|
-
return proxy;
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
this.parent = parent;
|
|
48
|
-
this.clear = parent.addListener(key => {
|
|
49
|
-
if (this.active)
|
|
50
|
-
this.notify(key);
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
get using() {
|
|
54
|
-
return Array.from(this.watch.keys());
|
|
55
|
-
}
|
|
56
|
-
get(key, using) {
|
|
57
|
-
this.follow(key);
|
|
58
|
-
return using
|
|
59
|
-
? using(this)
|
|
60
|
-
: this.parent.state.get(key);
|
|
61
|
-
}
|
|
62
|
-
follow(key, value) {
|
|
63
|
-
if (value !== undefined)
|
|
64
|
-
this.watch.set(key, value);
|
|
65
|
-
else if (!this.watch.has(key))
|
|
66
|
-
this.watch.set(key, true);
|
|
67
|
-
}
|
|
68
|
-
commit() {
|
|
69
|
-
this.active = true;
|
|
70
|
-
this.dependant.forEach(x => x.commit());
|
|
71
|
-
}
|
|
72
|
-
release() {
|
|
73
|
-
this.clear();
|
|
74
|
-
this.dependant.forEach(x => x.release());
|
|
75
|
-
}
|
|
76
|
-
notify(key) {
|
|
77
|
-
const { parent, watch } = this;
|
|
78
|
-
const handler = watch.get(key);
|
|
79
|
-
if (!handler)
|
|
80
|
-
return;
|
|
81
|
-
if (typeof handler == "function")
|
|
82
|
-
handler();
|
|
83
|
-
const notify = this.onUpdate(key, parent);
|
|
84
|
-
if (notify) {
|
|
85
|
-
parent.waiting.add(update => {
|
|
86
|
-
this.latest = update.filter(k => watch.has(k));
|
|
87
|
-
});
|
|
88
|
-
parent.waiting.add(notify);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function subscriber(from) {
|
|
93
|
-
return REGISTER$1.get(from);
|
|
94
|
-
}
|
|
47
|
+
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
95
48
|
|
|
96
|
-
const Oops$
|
|
49
|
+
const Oops$9 = issues({
|
|
97
50
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
51
|
+
Destoryed: () => "Model is destroyed."
|
|
98
52
|
});
|
|
99
|
-
function
|
|
100
|
-
const error = Oops$
|
|
101
|
-
const promise = new Promise(resolve => {
|
|
102
|
-
const
|
|
103
|
-
|
|
53
|
+
function suspense(source, key) {
|
|
54
|
+
const error = Oops$9.NotReady(source.subject, key);
|
|
55
|
+
const promise = new Promise((resolve, reject) => {
|
|
56
|
+
const subs = source.observers.get(key);
|
|
57
|
+
const onUpdate = (key) => {
|
|
58
|
+
if (key)
|
|
104
59
|
return () => {
|
|
105
|
-
if (source.state
|
|
106
|
-
|
|
60
|
+
if (source.state[key] !== undefined) {
|
|
61
|
+
subs.delete(onUpdate);
|
|
107
62
|
resolve();
|
|
108
63
|
}
|
|
109
64
|
};
|
|
110
|
-
|
|
65
|
+
reject(Oops$9.Destoryed());
|
|
66
|
+
};
|
|
67
|
+
subs.add(onUpdate);
|
|
111
68
|
});
|
|
112
69
|
return assign(promise, {
|
|
113
70
|
toString: () => String(error),
|
|
@@ -137,49 +94,37 @@ function mayRetry(fn) {
|
|
|
137
94
|
return compute();
|
|
138
95
|
}
|
|
139
96
|
|
|
140
|
-
const Oops$
|
|
97
|
+
const Oops$8 = issues({
|
|
141
98
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
142
99
|
});
|
|
143
|
-
function createEffect(
|
|
144
|
-
return control(
|
|
100
|
+
function createEffect(source, callback) {
|
|
101
|
+
return control(source, self => {
|
|
102
|
+
let { subject } = self;
|
|
145
103
|
let unSet;
|
|
146
104
|
let busy = false;
|
|
147
|
-
function effect(value) {
|
|
148
|
-
if (typeof unSet == "function")
|
|
149
|
-
unSet();
|
|
150
|
-
unSet = callback.call(this, value);
|
|
151
|
-
if (unSet instanceof Promise)
|
|
152
|
-
unSet = undefined;
|
|
153
|
-
if (unSet && typeof unSet !== "function")
|
|
154
|
-
throw Oops$7.BadCallback();
|
|
155
|
-
}
|
|
156
105
|
function invoke() {
|
|
157
106
|
if (busy)
|
|
158
107
|
return;
|
|
159
108
|
const output = mayRetry(() => {
|
|
160
|
-
|
|
109
|
+
if (typeof unSet == "function")
|
|
110
|
+
unSet();
|
|
111
|
+
unSet = callback.call(subject, subject);
|
|
112
|
+
if (unSet instanceof Promise)
|
|
113
|
+
unSet = undefined;
|
|
114
|
+
if (unSet && typeof unSet !== "function")
|
|
115
|
+
throw Oops$8.BadCallback();
|
|
161
116
|
});
|
|
162
117
|
if (output instanceof Promise) {
|
|
163
118
|
output.finally(() => busy = false);
|
|
164
119
|
busy = true;
|
|
165
120
|
}
|
|
166
121
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (key === null) {
|
|
171
|
-
if (!keys.length)
|
|
172
|
-
invoke();
|
|
173
|
-
}
|
|
174
|
-
else if (keys.includes(key))
|
|
175
|
-
return invoke;
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
const sub = new Subscriber(controller, () => invoke);
|
|
179
|
-
model = sub.proxy;
|
|
122
|
+
let refresh;
|
|
123
|
+
subject = watch(subject, () => refresh);
|
|
124
|
+
self.followers.add(key => (key === null || refresh === null ? refresh : undefined));
|
|
180
125
|
invoke();
|
|
181
|
-
|
|
182
|
-
return () =>
|
|
126
|
+
refresh = invoke;
|
|
127
|
+
return () => refresh = null;
|
|
183
128
|
});
|
|
184
129
|
}
|
|
185
130
|
function createValueEffect(callback) {
|
|
@@ -195,162 +140,254 @@ function createValueEffect(callback) {
|
|
|
195
140
|
if (typeof out == "function")
|
|
196
141
|
unSet = out;
|
|
197
142
|
else
|
|
198
|
-
throw Oops$
|
|
143
|
+
throw Oops$8.BadCallback();
|
|
199
144
|
};
|
|
200
145
|
}
|
|
201
146
|
|
|
202
|
-
const Oops$
|
|
203
|
-
|
|
204
|
-
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
205
|
-
StrictUpdate: () => `Expected update but none in progress.`,
|
|
206
|
-
StrictNoUpdate: () => `Update is not expected but one is in progress!`
|
|
147
|
+
const Oops$7 = issues({
|
|
148
|
+
KeysExpected: (key) => `Key "${key}" was expected in current update.`
|
|
207
149
|
});
|
|
208
|
-
function addEventListener(source,
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
150
|
+
function addEventListener(source, select, callback, once) {
|
|
151
|
+
return control(source, self => {
|
|
152
|
+
const { subject } = self;
|
|
153
|
+
if (typeof select == "string")
|
|
154
|
+
select = [select];
|
|
155
|
+
if (select)
|
|
156
|
+
for (const key of select)
|
|
157
|
+
try {
|
|
158
|
+
void subject[key];
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
// TODO: should this be caught?
|
|
162
|
+
}
|
|
163
|
+
const removeListener = self.addListener(key => {
|
|
164
|
+
if (key === null)
|
|
165
|
+
callback.call(subject, null);
|
|
166
|
+
else if (!select || select.includes(key)) {
|
|
167
|
+
if (once)
|
|
222
168
|
removeListener();
|
|
223
|
-
return
|
|
169
|
+
return () => callback.call(subject, self.latest);
|
|
224
170
|
}
|
|
225
171
|
});
|
|
226
172
|
return removeListener;
|
|
227
173
|
});
|
|
228
174
|
}
|
|
229
|
-
function awaitUpdate(source,
|
|
230
|
-
const single = typeof arg1 == "string";
|
|
231
|
-
const keys = typeof arg1 == "string" ? [arg1] :
|
|
232
|
-
typeof arg1 == "object" ? arg1 :
|
|
233
|
-
undefined;
|
|
175
|
+
function awaitUpdate(source, select, timeout) {
|
|
234
176
|
return new Promise((resolve, reject) => {
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
resolve(null);
|
|
247
|
-
return;
|
|
177
|
+
if (timeout === 0) {
|
|
178
|
+
const self = control(source, true);
|
|
179
|
+
if (!self.frame.size)
|
|
180
|
+
resolve(false);
|
|
181
|
+
else if (typeof select == "string" && !self.frame.has(select))
|
|
182
|
+
reject(Oops$7.KeysExpected(select));
|
|
183
|
+
else {
|
|
184
|
+
const remove = self.addListener(() => {
|
|
185
|
+
remove();
|
|
186
|
+
return () => resolve(self.latest);
|
|
187
|
+
});
|
|
248
188
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const remove = addEventListener(source, select, resolve, true);
|
|
192
|
+
if (timeout > 0)
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
remove();
|
|
195
|
+
resolve(false);
|
|
196
|
+
}, timeout);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const Oops$6 = issues({
|
|
202
|
+
NotFound: (name) => `Could not find ${name} in context.`
|
|
203
|
+
});
|
|
204
|
+
function get$1(arg1, arg2) {
|
|
205
|
+
return Control.get(this, (refresh, context) => {
|
|
206
|
+
let onUpdate;
|
|
207
|
+
let value;
|
|
208
|
+
if (typeof arg1 !== "function") {
|
|
209
|
+
context(got => {
|
|
210
|
+
if (got)
|
|
211
|
+
value = arg1 === undefined
|
|
212
|
+
? Control.watch(got, () => onUpdate)
|
|
213
|
+
: got;
|
|
214
|
+
else if (arg1 !== false)
|
|
215
|
+
throw Oops$6.NotFound(this);
|
|
216
|
+
});
|
|
217
|
+
return {
|
|
218
|
+
mount() {
|
|
219
|
+
onUpdate = refresh;
|
|
220
|
+
return () => onUpdate = null;
|
|
221
|
+
},
|
|
222
|
+
render: () => value
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
let compute = arg1;
|
|
226
|
+
let suspense;
|
|
227
|
+
let getValue;
|
|
228
|
+
let factory;
|
|
229
|
+
let proxy;
|
|
230
|
+
context(got => {
|
|
231
|
+
if (!got)
|
|
232
|
+
throw Oops$6.NotFound(this);
|
|
233
|
+
proxy = Control.watch(got, () => factory ? null : onUpdate);
|
|
234
|
+
getValue = () => compute.call(proxy, proxy, forceUpdate);
|
|
235
|
+
value = getValue();
|
|
236
|
+
function forceUpdate(action) {
|
|
237
|
+
if (typeof action == "function")
|
|
238
|
+
action = action();
|
|
239
|
+
if (getValue)
|
|
240
|
+
didUpdate(getValue());
|
|
241
|
+
else
|
|
242
|
+
refresh();
|
|
243
|
+
if (action)
|
|
244
|
+
return action.finally(refresh);
|
|
262
245
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
246
|
+
});
|
|
247
|
+
if (value === null) {
|
|
248
|
+
getValue = undefined;
|
|
249
|
+
onUpdate = null;
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (typeof value == "function") {
|
|
253
|
+
const get = value;
|
|
254
|
+
Control.watch(proxy, () => onUpdate);
|
|
255
|
+
factory = true;
|
|
256
|
+
compute = () => get();
|
|
257
|
+
value = get();
|
|
258
|
+
}
|
|
259
|
+
const didUpdate = (got) => {
|
|
260
|
+
value = got;
|
|
261
|
+
if (suspense) {
|
|
262
|
+
suspense();
|
|
263
|
+
suspense = undefined;
|
|
266
264
|
}
|
|
267
265
|
else
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
266
|
+
refresh();
|
|
267
|
+
};
|
|
268
|
+
if (value instanceof Promise) {
|
|
269
|
+
onUpdate = null;
|
|
270
|
+
value.then(didUpdate);
|
|
271
|
+
value = undefined;
|
|
272
|
+
}
|
|
273
|
+
else
|
|
274
|
+
onUpdate = () => {
|
|
275
|
+
const next = getValue();
|
|
276
|
+
if (notEqual(value, next))
|
|
277
|
+
didUpdate(next);
|
|
278
|
+
};
|
|
279
|
+
return {
|
|
280
|
+
mount: () => () => {
|
|
281
|
+
onUpdate = null;
|
|
282
|
+
},
|
|
283
|
+
render: () => {
|
|
284
|
+
if (value !== undefined)
|
|
285
|
+
return value;
|
|
286
|
+
if (arg2)
|
|
287
|
+
throw new Promise(res => {
|
|
288
|
+
suspense = res;
|
|
289
|
+
});
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/** Values are not equal for purposes of a refresh. */
|
|
296
|
+
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
297
|
+
!Array.isArray(b) ||
|
|
298
|
+
a.length !== b.length ||
|
|
299
|
+
a.some((x, i) => x !== b[i])));
|
|
300
|
+
|
|
301
|
+
function use$1(arg1, arg2) {
|
|
302
|
+
const render = Control.use((refresh) => {
|
|
303
|
+
let onUpdate;
|
|
304
|
+
let applyProps = typeof arg1 === "object";
|
|
305
|
+
const instance = this.new();
|
|
306
|
+
const proxy = Control.watch(instance, () => onUpdate);
|
|
307
|
+
if (typeof arg1 == "function")
|
|
308
|
+
arg1(instance);
|
|
309
|
+
return {
|
|
310
|
+
instance,
|
|
311
|
+
mount() {
|
|
312
|
+
onUpdate = refresh;
|
|
313
|
+
return () => {
|
|
314
|
+
onUpdate = null;
|
|
315
|
+
instance.null();
|
|
316
|
+
};
|
|
317
|
+
},
|
|
318
|
+
render(props) {
|
|
319
|
+
if (applyProps) {
|
|
320
|
+
onUpdate = undefined;
|
|
321
|
+
applyProps = !!arg2;
|
|
322
|
+
for (const key in props)
|
|
323
|
+
if (instance.hasOwnProperty(key))
|
|
324
|
+
instance[key] = props[key];
|
|
325
|
+
instance.on(0).then(() => onUpdate = refresh);
|
|
279
326
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
setTimeout(() => timeout(`${arg2}ms`), arg2);
|
|
327
|
+
return proxy;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
284
330
|
});
|
|
331
|
+
return render(arg1);
|
|
285
332
|
}
|
|
286
333
|
|
|
287
|
-
const Oops$5 = issues({
|
|
288
|
-
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`,
|
|
289
|
-
NoAdapter: (method) => `Can't call Model.${method} without an adapter.`
|
|
290
|
-
});
|
|
291
334
|
class Model {
|
|
292
335
|
constructor(id) {
|
|
293
|
-
new Control(this);
|
|
294
|
-
|
|
295
|
-
|
|
336
|
+
new Control(this, id);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Reference to `this` without a subscription.
|
|
340
|
+
* Use to obtain full reference from a destructure.
|
|
341
|
+
*/
|
|
342
|
+
get is() {
|
|
343
|
+
return this;
|
|
296
344
|
}
|
|
297
345
|
on(arg1, arg2, arg3) {
|
|
298
346
|
if (typeof arg1 == "function")
|
|
299
|
-
return createEffect(this
|
|
300
|
-
if (typeof
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
347
|
+
return createEffect(this, arg1);
|
|
348
|
+
if (typeof arg1 == "number") {
|
|
349
|
+
arg2 = arg1;
|
|
350
|
+
arg1 = undefined;
|
|
351
|
+
}
|
|
352
|
+
return typeof arg2 == "function"
|
|
353
|
+
? addEventListener(this, arg1, arg2, arg3)
|
|
354
|
+
: awaitUpdate(this, arg1, arg2);
|
|
304
355
|
}
|
|
305
356
|
get(arg1, arg2) {
|
|
306
|
-
const { state } = control(this);
|
|
307
|
-
|
|
357
|
+
const { state } = control(this, true);
|
|
358
|
+
function values() {
|
|
308
359
|
if (typeof arg1 == "string")
|
|
309
|
-
return state
|
|
360
|
+
return state[arg1];
|
|
361
|
+
if (!arg1)
|
|
362
|
+
return Object.assign({}, state);
|
|
310
363
|
const output = {};
|
|
311
|
-
for (const key of arg1
|
|
312
|
-
output[key] = state
|
|
364
|
+
for (const key of arg1)
|
|
365
|
+
output[key] = state[key];
|
|
313
366
|
return output;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return this.on(arg1, () => arg2(extract()));
|
|
319
|
-
const timeout = typeof arg2 == "number" ? arg2 : undefined;
|
|
320
|
-
return this.on(arg1, timeout).then(extract);
|
|
367
|
+
}
|
|
368
|
+
return typeof arg2 == "function"
|
|
369
|
+
? this.on(arg1, () => arg2(values()))
|
|
370
|
+
: values();
|
|
321
371
|
}
|
|
322
372
|
set(arg1, arg2) {
|
|
323
|
-
const controller = control(this);
|
|
373
|
+
const controller = control(this, true);
|
|
324
374
|
const { state } = controller;
|
|
325
375
|
if (typeof arg1 == "string") {
|
|
326
376
|
controller.update(arg1);
|
|
327
|
-
if (1 in arguments)
|
|
328
|
-
|
|
329
|
-
state.set(arg1, arg2);
|
|
330
|
-
else if (arg1 in this) {
|
|
331
|
-
const method = this[arg1];
|
|
332
|
-
if (typeof method == "function")
|
|
333
|
-
method.call(this, arg2);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
377
|
+
if (1 in arguments && arg1 in state)
|
|
378
|
+
state[arg1] = arg2;
|
|
336
379
|
}
|
|
337
380
|
else if (typeof arg1 == "object")
|
|
338
|
-
for (const key in
|
|
339
|
-
if (
|
|
340
|
-
state
|
|
381
|
+
for (const key in state)
|
|
382
|
+
if (key in arg1 && (!arg2 || arg2.includes(key))) {
|
|
383
|
+
state[key] = arg1[key];
|
|
341
384
|
controller.update(key);
|
|
342
385
|
}
|
|
343
|
-
return
|
|
344
|
-
then: (callback) => {
|
|
345
|
-
if (!callback)
|
|
346
|
-
throw Oops$5.NoChaining();
|
|
347
|
-
controller.waiting.add(callback);
|
|
348
|
-
}
|
|
349
|
-
};
|
|
386
|
+
return awaitUpdate(this, undefined, 0);
|
|
350
387
|
}
|
|
351
388
|
/** Mark this instance for garbage collection. */
|
|
352
|
-
|
|
353
|
-
control(this).clear();
|
|
389
|
+
null() {
|
|
390
|
+
control(this, true).clear();
|
|
354
391
|
}
|
|
355
392
|
/**
|
|
356
393
|
* Creates a new instance of this controller.
|
|
@@ -361,18 +398,9 @@ class Model {
|
|
|
361
398
|
*/
|
|
362
399
|
static new(...args) {
|
|
363
400
|
const instance = new this(...args);
|
|
364
|
-
control(instance);
|
|
401
|
+
control(instance, true);
|
|
365
402
|
return instance;
|
|
366
403
|
}
|
|
367
|
-
static find() {
|
|
368
|
-
throw Oops$5.NoAdapter("find");
|
|
369
|
-
}
|
|
370
|
-
static get() {
|
|
371
|
-
throw Oops$5.NoAdapter("get");
|
|
372
|
-
}
|
|
373
|
-
static use() {
|
|
374
|
-
throw Oops$5.NoAdapter("use");
|
|
375
|
-
}
|
|
376
404
|
/**
|
|
377
405
|
* Static equivalent of `x instanceof this`.
|
|
378
406
|
*
|
|
@@ -383,10 +411,12 @@ class Model {
|
|
|
383
411
|
maybe.prototype instanceof this);
|
|
384
412
|
}
|
|
385
413
|
}
|
|
414
|
+
Model.get = get$1;
|
|
415
|
+
Model.use = use$1;
|
|
386
416
|
defineProperty(Model.prototype, "toString", {
|
|
387
417
|
configurable: true,
|
|
388
418
|
value() {
|
|
389
|
-
return `${this.constructor.name}-${this.id}`;
|
|
419
|
+
return `${this.constructor.name}-${control(this).id}`;
|
|
390
420
|
}
|
|
391
421
|
});
|
|
392
422
|
defineProperty(Model, "toString", {
|
|
@@ -395,129 +425,320 @@ defineProperty(Model, "toString", {
|
|
|
395
425
|
}
|
|
396
426
|
});
|
|
397
427
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
428
|
+
const Oops$5 = issues({
|
|
429
|
+
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
430
|
+
});
|
|
431
|
+
const INSTRUCTION = new Map();
|
|
432
|
+
const REGISTER = new WeakMap();
|
|
433
|
+
const OBSERVER = new WeakMap();
|
|
434
|
+
class Control {
|
|
435
|
+
constructor(subject, id = random()) {
|
|
436
|
+
this.subject = subject;
|
|
437
|
+
this.id = id;
|
|
438
|
+
this.frame = new Set();
|
|
439
|
+
this.followers = new Set();
|
|
440
|
+
this.observers = new Map([["", this.followers]]);
|
|
441
|
+
REGISTER.set(subject, this);
|
|
442
|
+
}
|
|
443
|
+
add(key) {
|
|
444
|
+
const { value } = getOwnPropertyDescriptor(this.subject, key);
|
|
445
|
+
const instruction = INSTRUCTION.get(value);
|
|
446
|
+
if (typeof instruction == "function") {
|
|
447
|
+
INSTRUCTION.delete(value);
|
|
448
|
+
instruction(key, this);
|
|
449
|
+
}
|
|
450
|
+
else if (value instanceof Model)
|
|
451
|
+
setRecursive(this, key, value);
|
|
452
|
+
else if (typeof value != "function")
|
|
453
|
+
this.watch(key, { value });
|
|
454
|
+
}
|
|
455
|
+
watch(key, output) {
|
|
456
|
+
const { state } = this;
|
|
457
|
+
const { get, set, enumerable } = output;
|
|
458
|
+
const subs = new Set();
|
|
459
|
+
this.observers.set(key, subs);
|
|
411
460
|
if ("value" in output)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
defineProperty(control.subject, key, {
|
|
461
|
+
state[key] = output.value;
|
|
462
|
+
defineProperty(this.subject, key, {
|
|
415
463
|
enumerable,
|
|
416
|
-
set:
|
|
464
|
+
set: set === false
|
|
417
465
|
? undefined
|
|
418
|
-
:
|
|
466
|
+
: this.ref(key, set),
|
|
419
467
|
get() {
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
468
|
+
const event = OBSERVER.get(this);
|
|
469
|
+
if (event)
|
|
470
|
+
subs.add(event);
|
|
471
|
+
const value = get ? get(this) : state[key];
|
|
472
|
+
return event && value instanceof Model
|
|
473
|
+
? watch(value, event)
|
|
474
|
+
: value;
|
|
424
475
|
}
|
|
425
476
|
});
|
|
477
|
+
}
|
|
478
|
+
ref(key, callback) {
|
|
479
|
+
const { state, subject } = this;
|
|
480
|
+
return (value) => {
|
|
481
|
+
if (value !== state[key])
|
|
482
|
+
switch (callback && callback.call(subject, value)) {
|
|
483
|
+
case undefined:
|
|
484
|
+
state[key] = value;
|
|
485
|
+
case true:
|
|
486
|
+
this.update(key);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
update(key) {
|
|
491
|
+
const { frame } = this;
|
|
492
|
+
if (frame.has(key))
|
|
493
|
+
return;
|
|
494
|
+
if (!frame.size) {
|
|
495
|
+
this.latest = undefined;
|
|
496
|
+
requestUpdateFrame(() => {
|
|
497
|
+
this.latest = Array.from(frame);
|
|
498
|
+
this.followers.forEach(cb => {
|
|
499
|
+
const notify = cb(undefined, this);
|
|
500
|
+
if (notify)
|
|
501
|
+
requestUpdateFrame(notify);
|
|
502
|
+
});
|
|
503
|
+
frame.clear();
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
frame.add(key);
|
|
507
|
+
for (const k of ["", key]) {
|
|
508
|
+
const subs = this.observers.get(k);
|
|
509
|
+
subs && subs.forEach(cb => {
|
|
510
|
+
const notify = cb(key, this);
|
|
511
|
+
if (notify === null)
|
|
512
|
+
subs.delete(cb);
|
|
513
|
+
else if (notify)
|
|
514
|
+
requestUpdateFrame(notify);
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
addListener(fn) {
|
|
519
|
+
this.followers.add(fn);
|
|
520
|
+
return () => this.followers.delete(fn);
|
|
521
|
+
}
|
|
522
|
+
clear() {
|
|
523
|
+
this.observers.forEach(subs => {
|
|
524
|
+
subs.forEach(fn => {
|
|
525
|
+
const cb = fn(null, this);
|
|
526
|
+
cb && cb();
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
this.observers.clear();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
Control.after = new Set();
|
|
533
|
+
Control.before = new Set();
|
|
534
|
+
Control.pending = new Set();
|
|
535
|
+
Control.for = control;
|
|
536
|
+
Control.apply = apply;
|
|
537
|
+
Control.watch = watch;
|
|
538
|
+
const PENDING_INIT = new WeakMap();
|
|
539
|
+
function control(subject, ready) {
|
|
540
|
+
const control = REGISTER.get(subject.is);
|
|
541
|
+
const onReady = typeof ready == "function" && ready;
|
|
542
|
+
if (!control.state && ready) {
|
|
543
|
+
let waiting = PENDING_INIT.get(control);
|
|
544
|
+
if (!waiting)
|
|
545
|
+
PENDING_INIT.set(control, waiting = new Set());
|
|
546
|
+
if (onReady) {
|
|
547
|
+
let callback;
|
|
548
|
+
waiting.add(() => callback = onReady(control));
|
|
549
|
+
return () => callback && callback();
|
|
550
|
+
}
|
|
551
|
+
control.state = {};
|
|
552
|
+
for (const key in control.subject)
|
|
553
|
+
control.add(key);
|
|
554
|
+
waiting.forEach(cb => cb());
|
|
555
|
+
}
|
|
556
|
+
return onReady ? onReady(control) : control;
|
|
557
|
+
}
|
|
558
|
+
function requestUpdateFrame(event) {
|
|
559
|
+
const { after, before, pending } = Control;
|
|
560
|
+
if (!pending.size)
|
|
561
|
+
setTimeout(() => {
|
|
562
|
+
before.forEach(x => x());
|
|
563
|
+
pending.forEach(notify => {
|
|
564
|
+
try {
|
|
565
|
+
notify();
|
|
566
|
+
}
|
|
567
|
+
catch (err) {
|
|
568
|
+
console.error(err);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
pending.clear();
|
|
572
|
+
after.forEach(x => x());
|
|
573
|
+
}, 0);
|
|
574
|
+
pending.add(event);
|
|
575
|
+
}
|
|
576
|
+
function setRecursive(on, key, value) {
|
|
577
|
+
const set = (next) => {
|
|
578
|
+
if (next instanceof value.constructor) {
|
|
579
|
+
on.state[key] = next;
|
|
580
|
+
control(next).parent = on.subject;
|
|
581
|
+
control(next, true);
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
throw Oops$5.BadAssignment(`${on.subject}.${key}`, value.constructor, next);
|
|
585
|
+
};
|
|
586
|
+
on.watch(key, { set });
|
|
587
|
+
set(value);
|
|
588
|
+
}
|
|
589
|
+
function watch(on, cb) {
|
|
590
|
+
if (!on.hasOwnProperty("is"))
|
|
591
|
+
on = defineProperty(create(on), "is", { value: on });
|
|
592
|
+
OBSERVER.set(on, cb);
|
|
593
|
+
return on;
|
|
594
|
+
}
|
|
595
|
+
function apply(instruction) {
|
|
596
|
+
const placeholder = Symbol("instruction");
|
|
597
|
+
INSTRUCTION.set(placeholder, (key, onto) => {
|
|
598
|
+
delete onto.subject[key];
|
|
599
|
+
const output = instruction.call(onto, key, onto);
|
|
600
|
+
if (output)
|
|
601
|
+
onto.watch(key, typeof output == "function" ? { get: output } : output);
|
|
426
602
|
});
|
|
427
603
|
return placeholder;
|
|
604
|
+
}
|
|
605
|
+
/** Random alphanumberic of length 6; will always start with a letter. */
|
|
606
|
+
function random() {
|
|
607
|
+
return (Math.random() * 0.722 + 0.278).toString(36).substring(2, 8).toUpperCase();
|
|
428
608
|
}
|
|
429
609
|
|
|
430
610
|
const Oops$4 = issues({
|
|
611
|
+
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
612
|
+
});
|
|
613
|
+
function run(task) {
|
|
614
|
+
return apply((key, control) => {
|
|
615
|
+
let pending = false;
|
|
616
|
+
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
617
|
+
if (pending)
|
|
618
|
+
return Promise.reject(Oops$4.DuplicatePending(key));
|
|
619
|
+
pending = true;
|
|
620
|
+
control.update(key);
|
|
621
|
+
try {
|
|
622
|
+
return yield mayRetry(() => (task.apply(control.subject, args)));
|
|
623
|
+
}
|
|
624
|
+
finally {
|
|
625
|
+
pending = false;
|
|
626
|
+
control.update(key);
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
control.state[key] = undefined;
|
|
630
|
+
defineProperty(invoke, "active", {
|
|
631
|
+
get: () => pending
|
|
632
|
+
});
|
|
633
|
+
return {
|
|
634
|
+
value: invoke,
|
|
635
|
+
set: false
|
|
636
|
+
};
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const Oops$3 = issues({
|
|
431
641
|
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
|
|
432
642
|
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} ${parent}.${property}.`,
|
|
433
|
-
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}
|
|
643
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}.`,
|
|
644
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
645
|
+
AmbientRequired: (requested, requester) => `Attempted to find an instance of ${requested} in context. It is required by ${requester}, but one could not be found.`
|
|
434
646
|
});
|
|
435
647
|
function get(arg0, arg1) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
let { subject } = this;
|
|
648
|
+
return apply((key, control) => {
|
|
649
|
+
let { subject } = control;
|
|
439
650
|
if (typeof arg0 == "symbol")
|
|
440
|
-
throw Oops$
|
|
651
|
+
throw Oops$3.PeerNotAllowed(subject, key);
|
|
441
652
|
let source = cb => cb(subject);
|
|
442
653
|
if (arg0 instanceof Model)
|
|
443
654
|
subject = arg0;
|
|
444
|
-
else if (Model.isTypeof(arg0))
|
|
445
|
-
|
|
655
|
+
else if (Model.isTypeof(arg0)) {
|
|
656
|
+
const { parent } = control;
|
|
657
|
+
if (!parent) {
|
|
658
|
+
if (arg1 === true)
|
|
659
|
+
throw Oops$3.Required(arg0, subject);
|
|
660
|
+
source = callback => Control.has(arg0, subject, got => {
|
|
661
|
+
if (got)
|
|
662
|
+
callback(got);
|
|
663
|
+
else if (arg1 !== false)
|
|
664
|
+
throw Oops$3.AmbientRequired(arg0, subject);
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
else if (!arg0 || parent instanceof arg0)
|
|
668
|
+
subject = parent;
|
|
669
|
+
else
|
|
670
|
+
throw Oops$3.Unexpected(arg0, subject, parent);
|
|
671
|
+
}
|
|
446
672
|
else if (typeof arg0 == "function")
|
|
447
673
|
arg1 = arg0.call(subject, key, subject);
|
|
448
674
|
return typeof arg1 == "function"
|
|
449
|
-
? computed(
|
|
450
|
-
: recursive(
|
|
675
|
+
? computed(control, key, source, arg1)
|
|
676
|
+
: recursive(control, key, source, arg1);
|
|
451
677
|
});
|
|
452
678
|
}
|
|
453
|
-
function getParentForGetInstruction(type, relativeTo, required) {
|
|
454
|
-
const item = getParent(relativeTo, type);
|
|
455
|
-
return callback => {
|
|
456
|
-
if (item)
|
|
457
|
-
callback(item);
|
|
458
|
-
else if (required)
|
|
459
|
-
throw Oops$4.Required(type, relativeTo.constructor);
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
679
|
function recursive(parent, key, source, required) {
|
|
463
|
-
const getter = getRecursive(key, parent);
|
|
464
680
|
let waiting;
|
|
465
|
-
source
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
681
|
+
if (source)
|
|
682
|
+
source((got) => {
|
|
683
|
+
parent.state[key] = got;
|
|
684
|
+
if (waiting)
|
|
685
|
+
parent.update(key);
|
|
686
|
+
});
|
|
470
687
|
waiting = true;
|
|
471
|
-
return (
|
|
472
|
-
const value = parent.state
|
|
473
|
-
if (
|
|
474
|
-
|
|
475
|
-
|
|
688
|
+
return () => {
|
|
689
|
+
const value = parent.state[key];
|
|
690
|
+
if (value)
|
|
691
|
+
return value;
|
|
692
|
+
if (required !== false)
|
|
693
|
+
throw suspense(parent, key);
|
|
476
694
|
};
|
|
477
695
|
}
|
|
696
|
+
const ORDER = new WeakMap();
|
|
697
|
+
const PENDING = new Set();
|
|
698
|
+
let OFFSET = 0;
|
|
478
699
|
function computed(parent, key, source, setter) {
|
|
479
700
|
const { state } = parent;
|
|
480
|
-
let
|
|
701
|
+
let proxy;
|
|
481
702
|
let active;
|
|
482
703
|
let isAsync;
|
|
483
|
-
let
|
|
484
|
-
let pending = KEYS.get(parent);
|
|
485
|
-
if (!order)
|
|
486
|
-
ORDER.set(parent, order = new Map());
|
|
487
|
-
if (!pending)
|
|
488
|
-
KEYS.set(parent, pending = new Set());
|
|
489
|
-
INFO.set(compute, key);
|
|
704
|
+
let reset;
|
|
490
705
|
function compute(initial) {
|
|
706
|
+
if (parent.frame.has(key))
|
|
707
|
+
return;
|
|
491
708
|
let next;
|
|
492
709
|
try {
|
|
493
|
-
next = setter.call(
|
|
710
|
+
next = setter.call(proxy, proxy);
|
|
494
711
|
}
|
|
495
712
|
catch (err) {
|
|
496
|
-
Oops$
|
|
713
|
+
Oops$3.Failed(parent.subject, key, initial).warn();
|
|
497
714
|
if (initial)
|
|
498
715
|
throw err;
|
|
499
716
|
console.error(err);
|
|
500
717
|
}
|
|
501
|
-
if (next !== state
|
|
502
|
-
state
|
|
718
|
+
if (next !== state[key]) {
|
|
719
|
+
state[key] = next;
|
|
503
720
|
if (!initial || isAsync)
|
|
504
721
|
parent.update(key);
|
|
505
722
|
}
|
|
506
723
|
}
|
|
507
724
|
function connect(model) {
|
|
508
|
-
|
|
725
|
+
if (reset)
|
|
726
|
+
reset();
|
|
727
|
+
let done;
|
|
728
|
+
reset = () => done = true;
|
|
729
|
+
proxy = watch(model, (_, control) => {
|
|
730
|
+
if (done)
|
|
731
|
+
return null;
|
|
509
732
|
if (control !== parent)
|
|
510
733
|
compute();
|
|
511
734
|
else
|
|
512
|
-
|
|
735
|
+
PENDING.add(compute);
|
|
513
736
|
});
|
|
514
|
-
local.watch.set(key, false);
|
|
515
737
|
try {
|
|
516
738
|
compute(true);
|
|
517
739
|
}
|
|
518
740
|
finally {
|
|
519
|
-
|
|
520
|
-
order.set(compute, order.size);
|
|
741
|
+
ORDER.set(compute, OFFSET++);
|
|
521
742
|
}
|
|
522
743
|
}
|
|
523
744
|
return () => {
|
|
@@ -526,297 +747,32 @@ function computed(parent, key, source, setter) {
|
|
|
526
747
|
source(connect);
|
|
527
748
|
isAsync = true;
|
|
528
749
|
}
|
|
529
|
-
if (!
|
|
530
|
-
parent
|
|
531
|
-
if (
|
|
750
|
+
if (!proxy)
|
|
751
|
+
throw suspense(parent, key);
|
|
752
|
+
if (PENDING.delete(compute))
|
|
532
753
|
compute();
|
|
533
|
-
return state
|
|
754
|
+
return state[key];
|
|
534
755
|
};
|
|
535
756
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const ORDER = new WeakMap();
|
|
539
|
-
function flushComputed(control) {
|
|
540
|
-
const pending = KEYS.get(control);
|
|
541
|
-
if (!pending || !pending.size)
|
|
542
|
-
return;
|
|
543
|
-
const priority = ORDER.get(control);
|
|
544
|
-
while (pending.size) {
|
|
757
|
+
function flushComputed() {
|
|
758
|
+
while (PENDING.size) {
|
|
545
759
|
let compute;
|
|
546
|
-
for (const item of
|
|
547
|
-
if (!compute ||
|
|
760
|
+
for (const item of PENDING)
|
|
761
|
+
if (!compute || ORDER.get(item) < ORDER.get(compute))
|
|
548
762
|
compute = item;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
if (!control.frame.has(key))
|
|
552
|
-
compute();
|
|
763
|
+
PENDING.delete(compute);
|
|
764
|
+
compute();
|
|
553
765
|
}
|
|
554
|
-
pending.clear();
|
|
555
766
|
}
|
|
556
|
-
|
|
557
|
-
return Object.assign(get.bind(fn), { using });
|
|
558
|
-
}
|
|
559
|
-
get.using = using;
|
|
560
|
-
|
|
561
|
-
const REGISTER = new WeakMap();
|
|
562
|
-
const PENDING = new Map();
|
|
563
|
-
class Control {
|
|
564
|
-
constructor(subject) {
|
|
565
|
-
this.subject = subject;
|
|
566
|
-
this.frame = new Set();
|
|
567
|
-
this.waiting = new Set();
|
|
568
|
-
this.followers = new Set();
|
|
569
|
-
REGISTER.set(subject, this);
|
|
570
|
-
}
|
|
571
|
-
watch(key) {
|
|
572
|
-
const { subject, state } = this;
|
|
573
|
-
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
574
|
-
if (typeof value == "function")
|
|
575
|
-
return;
|
|
576
|
-
if (typeof value == "symbol") {
|
|
577
|
-
const instruction = PENDING.get(value);
|
|
578
|
-
if (instruction) {
|
|
579
|
-
delete subject[key];
|
|
580
|
-
PENDING.delete(value);
|
|
581
|
-
instruction(this, key);
|
|
582
|
-
}
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
state.set(key, value);
|
|
586
|
-
if (value instanceof Model) {
|
|
587
|
-
setRecursive(this, key, value);
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
defineProperty(subject, key, {
|
|
591
|
-
enumerable: false,
|
|
592
|
-
set: this.ref(key),
|
|
593
|
-
get() {
|
|
594
|
-
const local = subscriber(this);
|
|
595
|
-
return local
|
|
596
|
-
? local.get(key)
|
|
597
|
-
: state.get(key);
|
|
598
|
-
}
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
/** Throw suspense which resolves when key is set. */
|
|
602
|
-
waitFor(key) {
|
|
603
|
-
throw suspend(this, key);
|
|
604
|
-
}
|
|
605
|
-
addListener(listener) {
|
|
606
|
-
this.followers.add(listener);
|
|
607
|
-
return () => {
|
|
608
|
-
this.followers.delete(listener);
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
ref(key, handler) {
|
|
612
|
-
const { subject, state } = this;
|
|
613
|
-
return (value) => {
|
|
614
|
-
if (state.get(key) == value)
|
|
615
|
-
return;
|
|
616
|
-
if (handler)
|
|
617
|
-
switch (handler.call(subject, value)) {
|
|
618
|
-
case true:
|
|
619
|
-
this.update(key);
|
|
620
|
-
case false:
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
state.set(key, value);
|
|
624
|
-
this.update(key);
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
update(key) {
|
|
628
|
-
const { followers, frame, waiting } = this;
|
|
629
|
-
if (frame.has(key))
|
|
630
|
-
return;
|
|
631
|
-
else if (!frame.size)
|
|
632
|
-
setTimeout(() => {
|
|
633
|
-
flushComputed(this);
|
|
634
|
-
const keys = this.latest = Array.from(frame);
|
|
635
|
-
setTimeout(() => this.latest = undefined, 0);
|
|
636
|
-
frame.clear();
|
|
637
|
-
for (const notify of waiting)
|
|
638
|
-
try {
|
|
639
|
-
waiting.delete(notify);
|
|
640
|
-
notify(keys);
|
|
641
|
-
}
|
|
642
|
-
catch (err) {
|
|
643
|
-
console.error(err);
|
|
644
|
-
}
|
|
645
|
-
}, 0);
|
|
646
|
-
frame.add(key);
|
|
647
|
-
for (const callback of followers) {
|
|
648
|
-
const event = callback(key, this);
|
|
649
|
-
if (typeof event == "function")
|
|
650
|
-
waiting.add(event);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
clear() {
|
|
654
|
-
const listeners = [...this.followers];
|
|
655
|
-
this.followers.clear();
|
|
656
|
-
listeners.forEach(x => x(null, this));
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
Control.get = controller;
|
|
660
|
-
Control.for = control;
|
|
661
|
-
function controller(from) {
|
|
662
|
-
if ("is" in from)
|
|
663
|
-
from = from.is;
|
|
664
|
-
return REGISTER.get(from);
|
|
665
|
-
}
|
|
666
|
-
function control(subject, cb) {
|
|
667
|
-
const control = controller(subject) || new Control(subject);
|
|
668
|
-
if (!control.state) {
|
|
669
|
-
const { waiting } = control;
|
|
670
|
-
if (cb) {
|
|
671
|
-
let callback;
|
|
672
|
-
waiting.add(() => {
|
|
673
|
-
callback = cb(control);
|
|
674
|
-
});
|
|
675
|
-
return () => {
|
|
676
|
-
if (callback)
|
|
677
|
-
callback();
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
control.state = new Map();
|
|
681
|
-
for (const key in subject)
|
|
682
|
-
control.watch(key);
|
|
683
|
-
control.waiting = new Set();
|
|
684
|
-
for (const cb of waiting)
|
|
685
|
-
cb([]);
|
|
686
|
-
}
|
|
687
|
-
return cb ? cb(control) : control;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
const Parent = new WeakMap();
|
|
691
|
-
const Oops$3 = issues({
|
|
692
|
-
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
693
|
-
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
694
|
-
});
|
|
695
|
-
function getParent(from, type) {
|
|
696
|
-
const value = Parent.get(from);
|
|
697
|
-
if (value && type && !(value instanceof type))
|
|
698
|
-
throw Oops$3.Unexpected(type, from, value);
|
|
699
|
-
return value;
|
|
700
|
-
}
|
|
701
|
-
function getRecursive(key, from) {
|
|
702
|
-
const context = new WeakMap();
|
|
703
|
-
const { state } = from;
|
|
704
|
-
return (local) => {
|
|
705
|
-
if (!context.has(local)) {
|
|
706
|
-
let reset;
|
|
707
|
-
const init = () => {
|
|
708
|
-
if (reset)
|
|
709
|
-
reset();
|
|
710
|
-
const value = state.get(key);
|
|
711
|
-
if (value && controller(value)) {
|
|
712
|
-
const child = new Subscriber(value, local.onUpdate);
|
|
713
|
-
if (local.active)
|
|
714
|
-
child.commit();
|
|
715
|
-
local.dependant.add(child);
|
|
716
|
-
context.set(local, child.proxy);
|
|
717
|
-
reset = () => {
|
|
718
|
-
child.release();
|
|
719
|
-
local.dependant.delete(child);
|
|
720
|
-
context.set(local, undefined);
|
|
721
|
-
reset = undefined;
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
};
|
|
725
|
-
local.follow(key, init);
|
|
726
|
-
init();
|
|
727
|
-
}
|
|
728
|
-
return context.get(local);
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
function setRecursive(controller, key, initial) {
|
|
732
|
-
const { state, subject } = controller;
|
|
733
|
-
const Type = initial.constructor;
|
|
734
|
-
let get;
|
|
735
|
-
const onUpdate = (next) => {
|
|
736
|
-
state.set(key, next);
|
|
737
|
-
if (!(next instanceof Type))
|
|
738
|
-
throw Oops$3.BadAssignment(`${subject}.${key}`, Type, String(next));
|
|
739
|
-
const getter = getRecursive(key, controller);
|
|
740
|
-
get = (local) => local ? getter(local) : state.get(key);
|
|
741
|
-
Parent.set(next, subject);
|
|
742
|
-
control(next);
|
|
743
|
-
return true;
|
|
744
|
-
};
|
|
745
|
-
onUpdate(initial);
|
|
746
|
-
defineProperty(subject, key, {
|
|
747
|
-
set: controller.ref(key, onUpdate),
|
|
748
|
-
get() {
|
|
749
|
-
const local = subscriber(this);
|
|
750
|
-
if (local)
|
|
751
|
-
local.follow(key);
|
|
752
|
-
return get(local);
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
/******************************************************************************
|
|
758
|
-
Copyright (c) Microsoft Corporation.
|
|
759
|
-
|
|
760
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
761
|
-
purpose with or without fee is hereby granted.
|
|
762
|
-
|
|
763
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
764
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
765
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
766
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
767
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
768
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
769
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
770
|
-
***************************************************************************** */
|
|
771
|
-
|
|
772
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
773
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
774
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
775
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
776
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
777
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
778
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
const Oops$2 = issues({
|
|
783
|
-
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
784
|
-
});
|
|
785
|
-
function run(task) {
|
|
786
|
-
return add(function run(key) {
|
|
787
|
-
let pending = false;
|
|
788
|
-
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
789
|
-
if (pending)
|
|
790
|
-
return Promise.reject(Oops$2.DuplicatePending(key));
|
|
791
|
-
pending = true;
|
|
792
|
-
this.update(key);
|
|
793
|
-
try {
|
|
794
|
-
return yield mayRetry(() => (task.apply(this.subject, args)));
|
|
795
|
-
}
|
|
796
|
-
finally {
|
|
797
|
-
pending = false;
|
|
798
|
-
this.update(key);
|
|
799
|
-
}
|
|
800
|
-
});
|
|
801
|
-
this.state.set(key, undefined);
|
|
802
|
-
defineProperty(invoke, "active", {
|
|
803
|
-
get: () => pending
|
|
804
|
-
});
|
|
805
|
-
return {
|
|
806
|
-
value: invoke,
|
|
807
|
-
set: false
|
|
808
|
-
};
|
|
809
|
-
});
|
|
810
|
-
}
|
|
767
|
+
Control.before.add(flushComputed);
|
|
811
768
|
|
|
812
769
|
function ref(arg, mapper) {
|
|
813
|
-
return
|
|
770
|
+
return apply((key, source) => {
|
|
814
771
|
let value = {};
|
|
815
|
-
this.state.set(key, undefined);
|
|
816
772
|
if (typeof arg != "object")
|
|
817
|
-
value = createRef(
|
|
773
|
+
value = createRef(source, key, arg);
|
|
818
774
|
else
|
|
819
|
-
control(arg).state
|
|
775
|
+
for (const key in control(arg, true).state) {
|
|
820
776
|
defineProperty(value, key, mapper ? {
|
|
821
777
|
configurable: true,
|
|
822
778
|
get() {
|
|
@@ -825,28 +781,30 @@ function ref(arg, mapper) {
|
|
|
825
781
|
return out;
|
|
826
782
|
}
|
|
827
783
|
} : {
|
|
828
|
-
value: createRef(
|
|
784
|
+
value: createRef(source, key)
|
|
829
785
|
});
|
|
830
|
-
}
|
|
831
|
-
|
|
786
|
+
}
|
|
787
|
+
source.state[key] = undefined;
|
|
788
|
+
source.observers.set(key, new Set());
|
|
789
|
+
defineProperty(source.subject, key, { value });
|
|
832
790
|
});
|
|
833
791
|
}
|
|
834
792
|
function createRef(src, key, cb) {
|
|
835
793
|
const refObjectFunction = src.ref(key, cb && createValueEffect(cb));
|
|
836
794
|
defineProperty(refObjectFunction, "current", {
|
|
837
795
|
set: refObjectFunction,
|
|
838
|
-
get: () => src.state
|
|
796
|
+
get: () => src.state[key]
|
|
839
797
|
});
|
|
840
798
|
return refObjectFunction;
|
|
841
799
|
}
|
|
842
800
|
|
|
843
|
-
const Oops$
|
|
801
|
+
const Oops$2 = issues({
|
|
844
802
|
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
845
803
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
846
804
|
});
|
|
847
805
|
function set(value, argument) {
|
|
848
|
-
return
|
|
849
|
-
const { state, subject } =
|
|
806
|
+
return apply((key, control) => {
|
|
807
|
+
const { state, subject } = control;
|
|
850
808
|
if (typeof value == "function" || value instanceof Promise) {
|
|
851
809
|
const required = argument !== false;
|
|
852
810
|
let getter;
|
|
@@ -857,24 +815,24 @@ function set(value, argument) {
|
|
|
857
815
|
let pending;
|
|
858
816
|
let error;
|
|
859
817
|
if (value instanceof Promise) {
|
|
860
|
-
state
|
|
818
|
+
state[key] = undefined;
|
|
861
819
|
pending = value
|
|
862
820
|
.catch(err => error = err)
|
|
863
821
|
.then(val => {
|
|
864
|
-
state
|
|
822
|
+
state[key] = val;
|
|
865
823
|
return val;
|
|
866
824
|
})
|
|
867
825
|
.finally(() => {
|
|
868
826
|
pending = undefined;
|
|
869
|
-
|
|
827
|
+
control.update(key);
|
|
870
828
|
});
|
|
871
829
|
}
|
|
872
830
|
else
|
|
873
|
-
state
|
|
831
|
+
state[key] = value;
|
|
874
832
|
const suspend = () => {
|
|
875
833
|
if (required === false)
|
|
876
834
|
return undefined;
|
|
877
|
-
const issue = Oops$
|
|
835
|
+
const issue = Oops$2.NotReady(subject, key);
|
|
878
836
|
assign(pending, {
|
|
879
837
|
message: issue.message,
|
|
880
838
|
stack: issue.stack
|
|
@@ -886,12 +844,11 @@ function set(value, argument) {
|
|
|
886
844
|
throw error;
|
|
887
845
|
if (pending)
|
|
888
846
|
return suspend();
|
|
889
|
-
|
|
890
|
-
return state.get(key);
|
|
847
|
+
return state[key];
|
|
891
848
|
};
|
|
892
849
|
}
|
|
893
850
|
catch (err) {
|
|
894
|
-
Oops$
|
|
851
|
+
Oops$2.ComputeFailed(subject, key).warn();
|
|
895
852
|
throw err;
|
|
896
853
|
}
|
|
897
854
|
};
|
|
@@ -904,13 +861,13 @@ function set(value, argument) {
|
|
|
904
861
|
};
|
|
905
862
|
}
|
|
906
863
|
if (value !== undefined)
|
|
907
|
-
state
|
|
864
|
+
state[key] = value;
|
|
908
865
|
return {
|
|
909
866
|
get: () => {
|
|
910
|
-
if (state
|
|
911
|
-
return state
|
|
867
|
+
if (key in state)
|
|
868
|
+
return state[key];
|
|
912
869
|
else
|
|
913
|
-
|
|
870
|
+
throw suspense(control, key);
|
|
914
871
|
},
|
|
915
872
|
set: typeof argument == "function"
|
|
916
873
|
? createValueEffect(argument)
|
|
@@ -919,180 +876,27 @@ function set(value, argument) {
|
|
|
919
876
|
});
|
|
920
877
|
}
|
|
921
878
|
|
|
922
|
-
const
|
|
923
|
-
function keyed(control, property, initial) {
|
|
924
|
-
const init = createProxy(emit, watch);
|
|
925
|
-
const frozen = new Set();
|
|
926
|
-
const context = new Map();
|
|
927
|
-
const users = new Map();
|
|
928
|
-
const watched = new WeakMap();
|
|
929
|
-
const update = new Set();
|
|
930
|
-
let managed = init(initial);
|
|
931
|
-
function watch(on, key) {
|
|
932
|
-
const include = watched.get(on);
|
|
933
|
-
if (include)
|
|
934
|
-
include.add(key);
|
|
935
|
-
}
|
|
936
|
-
function emit(key) {
|
|
937
|
-
control.update(property);
|
|
938
|
-
control.waiting.add(() => frozen.clear());
|
|
939
|
-
update.forEach(notify => notify(key));
|
|
940
|
-
}
|
|
941
|
-
function subscribe(local) {
|
|
942
|
-
const proxy = create(managed);
|
|
943
|
-
let watch = users.get(local);
|
|
944
|
-
if (!watch) {
|
|
945
|
-
const using = watch = new Set();
|
|
946
|
-
users.set(local, using);
|
|
947
|
-
function onEvent(key) {
|
|
948
|
-
if (frozen.has(local))
|
|
949
|
-
return;
|
|
950
|
-
if (key === ANY || using.has(key) || using.has(ANY)) {
|
|
951
|
-
const refresh = local.onUpdate(property, control);
|
|
952
|
-
if (refresh) {
|
|
953
|
-
frozen.add(local);
|
|
954
|
-
refresh();
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
local.follow(property, false);
|
|
959
|
-
local.dependant.add({
|
|
960
|
-
commit() {
|
|
961
|
-
if (using.size === 0)
|
|
962
|
-
using.add(ANY);
|
|
963
|
-
update.add(onEvent);
|
|
964
|
-
},
|
|
965
|
-
release() {
|
|
966
|
-
update.delete(onEvent);
|
|
967
|
-
}
|
|
968
|
-
});
|
|
969
|
-
}
|
|
970
|
-
watched.set(proxy, watch);
|
|
971
|
-
context.set(local, proxy);
|
|
972
|
-
return proxy;
|
|
973
|
-
}
|
|
974
|
-
control.addListener(key => {
|
|
975
|
-
if (key === null) {
|
|
976
|
-
update.clear();
|
|
977
|
-
context.clear();
|
|
978
|
-
}
|
|
979
|
-
});
|
|
980
|
-
return {
|
|
981
|
-
value: initial,
|
|
982
|
-
get(local) {
|
|
983
|
-
return local ?
|
|
984
|
-
context.get(local) || subscribe(local) :
|
|
985
|
-
managed;
|
|
986
|
-
},
|
|
987
|
-
set(next) {
|
|
988
|
-
control.state.set(property, next);
|
|
989
|
-
managed = init(next);
|
|
990
|
-
context.clear();
|
|
991
|
-
emit(ANY);
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
function createProxy(emit, watch) {
|
|
996
|
-
return (from) => {
|
|
997
|
-
const proxy = create(from);
|
|
998
|
-
assign(proxy, {
|
|
999
|
-
from,
|
|
1000
|
-
delete(key) {
|
|
1001
|
-
// TODO: this commit's fix needs tests.
|
|
1002
|
-
// Was not cause by coverage.
|
|
1003
|
-
const out = from.delete(key);
|
|
1004
|
-
emit(key);
|
|
1005
|
-
return out;
|
|
1006
|
-
},
|
|
1007
|
-
clear() {
|
|
1008
|
-
from.clear();
|
|
1009
|
-
emit(ANY);
|
|
1010
|
-
},
|
|
1011
|
-
has(key) {
|
|
1012
|
-
watch(this, key);
|
|
1013
|
-
return from.has(key);
|
|
1014
|
-
},
|
|
1015
|
-
keys() {
|
|
1016
|
-
watch(this, ANY);
|
|
1017
|
-
return from.keys();
|
|
1018
|
-
},
|
|
1019
|
-
values() {
|
|
1020
|
-
watch(this, ANY);
|
|
1021
|
-
return from.values();
|
|
1022
|
-
},
|
|
1023
|
-
entries() {
|
|
1024
|
-
watch(this, ANY);
|
|
1025
|
-
return from.entries();
|
|
1026
|
-
},
|
|
1027
|
-
forEach(callbackfn, thisArg) {
|
|
1028
|
-
const acc = [];
|
|
1029
|
-
from.forEach((a, b, c) => {
|
|
1030
|
-
const result = callbackfn.call(thisArg, a, b, c);
|
|
1031
|
-
if (result !== undefined)
|
|
1032
|
-
acc.push(result);
|
|
1033
|
-
});
|
|
1034
|
-
watch(this, ANY);
|
|
1035
|
-
return acc;
|
|
1036
|
-
},
|
|
1037
|
-
[Symbol.iterator]() {
|
|
1038
|
-
watch(this, ANY);
|
|
1039
|
-
return from[Symbol.iterator]();
|
|
1040
|
-
},
|
|
1041
|
-
}, from instanceof Set
|
|
1042
|
-
? {
|
|
1043
|
-
add(key) {
|
|
1044
|
-
from.add(key);
|
|
1045
|
-
emit(key);
|
|
1046
|
-
return this;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
: {
|
|
1050
|
-
get(key) {
|
|
1051
|
-
watch(this, ANY);
|
|
1052
|
-
return from.get(key);
|
|
1053
|
-
},
|
|
1054
|
-
set(key, value) {
|
|
1055
|
-
from.set(key, value);
|
|
1056
|
-
emit(key);
|
|
1057
|
-
return this;
|
|
1058
|
-
}
|
|
1059
|
-
});
|
|
1060
|
-
defineProperty(proxy, "size", {
|
|
1061
|
-
get() {
|
|
1062
|
-
watch(this, ANY);
|
|
1063
|
-
return from.size;
|
|
1064
|
-
}
|
|
1065
|
-
});
|
|
1066
|
-
return proxy;
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
const Oops = issues({
|
|
879
|
+
const Oops$1 = issues({
|
|
1071
880
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1072
881
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1073
882
|
});
|
|
1074
883
|
function use(input, argument) {
|
|
1075
|
-
return
|
|
1076
|
-
const { state, subject } =
|
|
884
|
+
return apply((key, source) => {
|
|
885
|
+
const { state, subject } = source;
|
|
1077
886
|
const required = argument !== false;
|
|
1078
887
|
let pending;
|
|
1079
888
|
let error;
|
|
1080
|
-
let get = (_local) => state.get(key);
|
|
1081
889
|
if (typeof input === "function") {
|
|
1082
890
|
if ("prototype" in input && input === input.prototype.constructor)
|
|
1083
891
|
input = new input();
|
|
1084
892
|
}
|
|
1085
893
|
else if (input && typeof input !== "object")
|
|
1086
|
-
throw Oops.BadArgument(typeof input);
|
|
1087
|
-
if (input instanceof Map || input instanceof Set)
|
|
1088
|
-
return keyed(this, key, input);
|
|
894
|
+
throw Oops$1.BadArgument(typeof input);
|
|
1089
895
|
const onUpdate = (next) => {
|
|
1090
|
-
state
|
|
896
|
+
state[key] = next;
|
|
1091
897
|
if (next) {
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
Parent.set(next, subject);
|
|
1095
|
-
control(next);
|
|
898
|
+
control(next).parent = subject;
|
|
899
|
+
control(next, true);
|
|
1096
900
|
}
|
|
1097
901
|
if (typeof argument == "function")
|
|
1098
902
|
argument(next);
|
|
@@ -1101,7 +905,7 @@ function use(input, argument) {
|
|
|
1101
905
|
const suspend = () => {
|
|
1102
906
|
if (required === false)
|
|
1103
907
|
return;
|
|
1104
|
-
const issue = Oops.NotReady(subject, key);
|
|
908
|
+
const issue = Oops$1.NotReady(subject, key);
|
|
1105
909
|
assign(pending, {
|
|
1106
910
|
message: issue.message,
|
|
1107
911
|
stack: issue.stack
|
|
@@ -1114,14 +918,14 @@ function use(input, argument) {
|
|
|
1114
918
|
input;
|
|
1115
919
|
if (output instanceof Promise) {
|
|
1116
920
|
pending = output
|
|
1117
|
-
.catch(err => error = err)
|
|
1118
921
|
.then(val => {
|
|
1119
922
|
onUpdate(val);
|
|
1120
923
|
return val;
|
|
1121
924
|
})
|
|
925
|
+
.catch(err => error = err)
|
|
1122
926
|
.finally(() => {
|
|
1123
927
|
pending = undefined;
|
|
1124
|
-
|
|
928
|
+
source.update(key);
|
|
1125
929
|
});
|
|
1126
930
|
return;
|
|
1127
931
|
}
|
|
@@ -1131,60 +935,28 @@ function use(input, argument) {
|
|
|
1131
935
|
initialize();
|
|
1132
936
|
return {
|
|
1133
937
|
set: onUpdate,
|
|
1134
|
-
get(
|
|
938
|
+
get() {
|
|
1135
939
|
if (pending)
|
|
1136
940
|
return suspend();
|
|
1137
941
|
if (error)
|
|
1138
942
|
throw error;
|
|
1139
|
-
if (!
|
|
943
|
+
if (!(key in state))
|
|
1140
944
|
initialize();
|
|
1141
945
|
if (pending)
|
|
1142
946
|
return suspend();
|
|
1143
|
-
return
|
|
947
|
+
return state[key];
|
|
1144
948
|
}
|
|
1145
949
|
};
|
|
1146
950
|
});
|
|
1147
951
|
}
|
|
1148
952
|
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1151
|
-
const UPDATE = "__update";
|
|
1152
|
-
const CONTROL = "__control";
|
|
1153
|
-
defineProperties(Model.prototype, {
|
|
1154
|
-
[CONTROL]: {
|
|
1155
|
-
get() {
|
|
1156
|
-
return controller(this);
|
|
1157
|
-
}
|
|
1158
|
-
},
|
|
1159
|
-
[LOCAL]: {
|
|
1160
|
-
get() {
|
|
1161
|
-
return subscriber(this);
|
|
1162
|
-
}
|
|
1163
|
-
},
|
|
1164
|
-
[STATE]: {
|
|
1165
|
-
get() {
|
|
1166
|
-
const { state } = controller(this);
|
|
1167
|
-
const output = {};
|
|
1168
|
-
state.forEach((value, key) => output[key] = value);
|
|
1169
|
-
return output;
|
|
1170
|
-
}
|
|
1171
|
-
},
|
|
1172
|
-
[UPDATE]: {
|
|
1173
|
-
get() {
|
|
1174
|
-
return (subscriber(this) || controller(this)).latest;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
953
|
+
const Oops = issues({
|
|
954
|
+
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined.`
|
|
1177
955
|
});
|
|
1178
|
-
|
|
1179
|
-
CONTROL,
|
|
1180
|
-
LOCAL,
|
|
1181
|
-
STATE,
|
|
1182
|
-
UPDATE
|
|
1183
|
-
};
|
|
1184
|
-
|
|
1185
|
-
class Register {
|
|
956
|
+
class Context {
|
|
1186
957
|
constructor() {
|
|
1187
|
-
this.table = new
|
|
958
|
+
this.table = new WeakMap();
|
|
959
|
+
this.input = new Map();
|
|
1188
960
|
}
|
|
1189
961
|
has(T) {
|
|
1190
962
|
let key = this.table.get(T);
|
|
@@ -1195,9 +967,16 @@ class Register {
|
|
|
1195
967
|
return key;
|
|
1196
968
|
}
|
|
1197
969
|
get(Type) {
|
|
1198
|
-
|
|
970
|
+
const result = this[this.has(Type)];
|
|
971
|
+
if (result === null)
|
|
972
|
+
throw Oops.MultipleExist(Type);
|
|
973
|
+
return result;
|
|
1199
974
|
}
|
|
1200
975
|
add(input, key) {
|
|
976
|
+
if (key && this.input.get(key) === input)
|
|
977
|
+
return typeof input == "object"
|
|
978
|
+
? input
|
|
979
|
+
: this[this.has(input)];
|
|
1201
980
|
let writable = true;
|
|
1202
981
|
let T;
|
|
1203
982
|
let I;
|
|
@@ -1220,12 +999,12 @@ class Register {
|
|
|
1220
999
|
T = getPrototypeOf(T);
|
|
1221
1000
|
} while (T !== Model);
|
|
1222
1001
|
if (key !== undefined)
|
|
1223
|
-
this.
|
|
1002
|
+
this.input.set(key, input);
|
|
1224
1003
|
return I;
|
|
1225
1004
|
}
|
|
1226
1005
|
push() {
|
|
1227
1006
|
const next = create(this);
|
|
1228
|
-
next.
|
|
1007
|
+
next.input = new Map();
|
|
1229
1008
|
return next;
|
|
1230
1009
|
}
|
|
1231
1010
|
pop() {
|
|
@@ -1237,21 +1016,48 @@ class Register {
|
|
|
1237
1016
|
delete this[key];
|
|
1238
1017
|
}
|
|
1239
1018
|
for (const model of items)
|
|
1240
|
-
model.
|
|
1019
|
+
model.null();
|
|
1020
|
+
this.input.clear();
|
|
1241
1021
|
}
|
|
1242
1022
|
}
|
|
1243
1023
|
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1024
|
+
const STATE = "__state";
|
|
1025
|
+
const UPDATE = "__update";
|
|
1026
|
+
const CONTROL = "__control";
|
|
1027
|
+
const PARENT = "__parent";
|
|
1028
|
+
defineProperties(Model.prototype, {
|
|
1029
|
+
[CONTROL]: {
|
|
1030
|
+
get() {
|
|
1031
|
+
return control(this);
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
[STATE]: {
|
|
1035
|
+
get() {
|
|
1036
|
+
return Object.assign({}, control(this).state);
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
[UPDATE]: {
|
|
1040
|
+
get() {
|
|
1041
|
+
return control(this).latest;
|
|
1042
|
+
}
|
|
1043
|
+
},
|
|
1044
|
+
[PARENT]: {
|
|
1045
|
+
get() {
|
|
1046
|
+
return control(this).parent;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
const Debug = {
|
|
1051
|
+
CONTROL,
|
|
1052
|
+
STATE,
|
|
1053
|
+
UPDATE,
|
|
1054
|
+
PARENT
|
|
1246
1055
|
};
|
|
1247
1056
|
|
|
1057
|
+
exports.Context = Context;
|
|
1248
1058
|
exports.Control = Control;
|
|
1249
1059
|
exports.Debug = Debug;
|
|
1250
|
-
exports.Internal = Internal;
|
|
1251
1060
|
exports.Model = Model;
|
|
1252
|
-
exports.Register = Register;
|
|
1253
|
-
exports.Subscriber = Subscriber;
|
|
1254
|
-
exports.add = add;
|
|
1255
1061
|
exports["default"] = Model;
|
|
1256
1062
|
exports.get = get;
|
|
1257
1063
|
exports.issues = issues;
|