@expressive/mvc 0.16.0 → 0.17.1
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 +105 -158
- package/lib/index.esm.js +537 -552
- package/lib/index.js +536 -556
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -8,6 +8,23 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
10
|
|
|
11
|
+
class Issue extends Error {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
// drop first line (error factory) in stack trace.
|
|
15
|
+
this.stack = this.stack.replace(/\n.+/, "");
|
|
16
|
+
}
|
|
17
|
+
warn() {
|
|
18
|
+
console.warn(this.message);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function issues(register) {
|
|
22
|
+
const Library = {};
|
|
23
|
+
for (const name in register)
|
|
24
|
+
Library[name] = (...args) => new Issue(register[name].apply(null, args));
|
|
25
|
+
return Library;
|
|
26
|
+
}
|
|
27
|
+
|
|
11
28
|
const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
12
29
|
const UID_CACHE = new WeakMap();
|
|
13
30
|
function assignWeak(into, from) {
|
|
@@ -22,28 +39,82 @@ function uid(object) {
|
|
|
22
39
|
return uid;
|
|
23
40
|
}
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.
|
|
42
|
+
const REGISTER$1 = new WeakMap();
|
|
43
|
+
class Subscriber {
|
|
44
|
+
constructor(parent, onUpdate, strict) {
|
|
45
|
+
this.parent = parent;
|
|
46
|
+
this.onUpdate = onUpdate;
|
|
47
|
+
this.strict = strict;
|
|
48
|
+
this.active = false;
|
|
49
|
+
this.dependant = new Set();
|
|
50
|
+
this.watch = new Map();
|
|
51
|
+
const proxy = create(parent.subject);
|
|
52
|
+
const reset = () => this.latest = undefined;
|
|
53
|
+
REGISTER$1.set(proxy, this);
|
|
54
|
+
defineProperty(this, "proxy", {
|
|
55
|
+
configurable: true,
|
|
56
|
+
get() {
|
|
57
|
+
setTimeout(reset, 0);
|
|
58
|
+
return proxy;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
this.clear = parent.addListener(key => {
|
|
62
|
+
if (this.active)
|
|
63
|
+
this.notify(key);
|
|
64
|
+
});
|
|
30
65
|
}
|
|
31
|
-
|
|
32
|
-
|
|
66
|
+
get using() {
|
|
67
|
+
return Array.from(this.watch.keys());
|
|
68
|
+
}
|
|
69
|
+
apply(values, keys) {
|
|
70
|
+
const { waiting, subject } = this.parent;
|
|
71
|
+
this.active = false;
|
|
72
|
+
if (!keys)
|
|
73
|
+
keys = getOwnPropertyNames(subject);
|
|
74
|
+
for (const key of keys)
|
|
75
|
+
if (key in values)
|
|
76
|
+
subject[key] = values[key];
|
|
77
|
+
waiting.add(() => this.active = true);
|
|
78
|
+
}
|
|
79
|
+
follow(key, value) {
|
|
80
|
+
if (value !== undefined)
|
|
81
|
+
this.watch.set(key, value);
|
|
82
|
+
else if (!this.watch.has(key))
|
|
83
|
+
this.watch.set(key, true);
|
|
84
|
+
}
|
|
85
|
+
commit() {
|
|
86
|
+
this.active = true;
|
|
87
|
+
this.dependant.forEach(x => x.commit());
|
|
88
|
+
}
|
|
89
|
+
release() {
|
|
90
|
+
this.clear();
|
|
91
|
+
this.dependant.forEach(x => x.release());
|
|
92
|
+
}
|
|
93
|
+
notify(key) {
|
|
94
|
+
const { parent, watch } = this;
|
|
95
|
+
const handler = watch.get(key);
|
|
96
|
+
if (!handler)
|
|
97
|
+
return;
|
|
98
|
+
if (typeof handler == "function")
|
|
99
|
+
handler();
|
|
100
|
+
const notify = this.onUpdate(key, parent);
|
|
101
|
+
if (notify) {
|
|
102
|
+
parent.waiting.add(update => {
|
|
103
|
+
this.latest = update.filter(k => watch.has(k));
|
|
104
|
+
});
|
|
105
|
+
parent.waiting.add(notify);
|
|
106
|
+
}
|
|
33
107
|
}
|
|
34
108
|
}
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
for (const name in register)
|
|
38
|
-
Library[name] = (...args) => new Issue(register[name].apply(null, args));
|
|
39
|
-
return Library;
|
|
109
|
+
function subscriber(from) {
|
|
110
|
+
return REGISTER$1.get(from);
|
|
40
111
|
}
|
|
41
112
|
|
|
42
|
-
const Oops$
|
|
113
|
+
const Oops$c = issues({
|
|
43
114
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
44
115
|
});
|
|
45
116
|
function suspend(source, key) {
|
|
46
|
-
const error = Oops$
|
|
117
|
+
const error = Oops$c.NotReady(source.subject, key);
|
|
47
118
|
const promise = new Promise(resolve => {
|
|
48
119
|
const release = source.addListener(forKey => {
|
|
49
120
|
if (forKey == key)
|
|
@@ -83,98 +154,87 @@ function mayRetry(fn) {
|
|
|
83
154
|
return compute();
|
|
84
155
|
}
|
|
85
156
|
|
|
86
|
-
const
|
|
87
|
-
|
|
157
|
+
const Parent = new WeakMap();
|
|
158
|
+
const Oops$b = issues({
|
|
159
|
+
BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`,
|
|
160
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
161
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
88
162
|
});
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
let pending = KEYS.get(self);
|
|
97
|
-
if (!order)
|
|
98
|
-
ORDER.set(self, order = new Map());
|
|
99
|
-
if (!pending)
|
|
100
|
-
KEYS.set(self, pending = new Set());
|
|
101
|
-
const compute = (initial) => {
|
|
102
|
-
try {
|
|
103
|
-
return setter.call(sub.proxy, sub.proxy);
|
|
104
|
-
}
|
|
105
|
-
catch (err) {
|
|
106
|
-
Oops$e.Failed(subject, key, initial).warn();
|
|
107
|
-
throw err;
|
|
108
|
-
}
|
|
163
|
+
function getParentForGetInstruction(type, relativeTo, required) {
|
|
164
|
+
const item = getParent(type, relativeTo);
|
|
165
|
+
return (_refresh) => {
|
|
166
|
+
if (item)
|
|
167
|
+
return item;
|
|
168
|
+
if (required)
|
|
169
|
+
throw Oops$b.Required(type.name, relativeTo);
|
|
109
170
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
171
|
+
}
|
|
172
|
+
function getParent(type, from) {
|
|
173
|
+
const value = Parent.get(from);
|
|
174
|
+
if (value && !(value instanceof type))
|
|
175
|
+
throw Oops$b.Unexpected(type.name, from, value);
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
function getRecursive(key, from) {
|
|
179
|
+
const context = new WeakMap();
|
|
180
|
+
const { state } = from;
|
|
181
|
+
return (local) => {
|
|
182
|
+
if (!state.has(key))
|
|
183
|
+
throw suspend(from, key);
|
|
184
|
+
if (!local)
|
|
185
|
+
return state.get(key);
|
|
186
|
+
if (!context.has(local)) {
|
|
187
|
+
let reset;
|
|
188
|
+
const init = () => {
|
|
189
|
+
if (reset)
|
|
190
|
+
reset();
|
|
191
|
+
const value = state.get(key);
|
|
192
|
+
if (value && controller(value)) {
|
|
193
|
+
const child = new Subscriber(control(value), local.onUpdate);
|
|
194
|
+
if (local.active)
|
|
195
|
+
child.commit();
|
|
196
|
+
local.dependant.add(child);
|
|
197
|
+
context.set(local, child.proxy);
|
|
198
|
+
reset = () => {
|
|
199
|
+
child.release();
|
|
200
|
+
local.dependant.delete(child);
|
|
201
|
+
context.set(local, undefined);
|
|
202
|
+
reset = undefined;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
local.follow(key, init);
|
|
207
|
+
init();
|
|
124
208
|
}
|
|
209
|
+
return context.get(local);
|
|
125
210
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
catch (e) {
|
|
140
|
-
throw e;
|
|
141
|
-
}
|
|
142
|
-
finally {
|
|
143
|
-
sub.commit();
|
|
144
|
-
order.set(refresh, order.size);
|
|
145
|
-
}
|
|
211
|
+
}
|
|
212
|
+
function setRecursive(controller, key, initial) {
|
|
213
|
+
const { state, subject } = controller;
|
|
214
|
+
const Type = initial.constructor;
|
|
215
|
+
let get;
|
|
216
|
+
const onUpdate = (next) => {
|
|
217
|
+
state.set(key, next);
|
|
218
|
+
if (!(next instanceof Type))
|
|
219
|
+
throw Oops$b.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
220
|
+
get = getRecursive(key, controller);
|
|
221
|
+
Parent.set(next, subject);
|
|
222
|
+
control(next);
|
|
223
|
+
return true;
|
|
146
224
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
225
|
+
onUpdate(initial);
|
|
226
|
+
defineProperty(subject, key, {
|
|
227
|
+
set: controller.ref(key, onUpdate),
|
|
228
|
+
get() {
|
|
229
|
+
const local = subscriber(this);
|
|
230
|
+
if (local)
|
|
231
|
+
local.follow(key);
|
|
232
|
+
return get(local);
|
|
152
233
|
}
|
|
153
|
-
|
|
154
|
-
if (value === undefined && required)
|
|
155
|
-
throw suspend(self, key);
|
|
156
|
-
return value;
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
function flush(control) {
|
|
160
|
-
const pending = KEYS.get(control);
|
|
161
|
-
if (!pending || !pending.size)
|
|
162
|
-
return;
|
|
163
|
-
const priority = ORDER.get(control);
|
|
164
|
-
while (pending.size) {
|
|
165
|
-
let compute;
|
|
166
|
-
for (const item of pending)
|
|
167
|
-
if (!compute || priority.get(item) < priority.get(compute))
|
|
168
|
-
compute = item;
|
|
169
|
-
pending.delete(compute);
|
|
170
|
-
const key = INFO.get(compute);
|
|
171
|
-
if (!control.frame.has(key))
|
|
172
|
-
compute();
|
|
173
|
-
}
|
|
174
|
-
pending.clear();
|
|
234
|
+
});
|
|
175
235
|
}
|
|
176
236
|
|
|
177
|
-
const Oops$
|
|
237
|
+
const Oops$a = issues({
|
|
178
238
|
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
179
239
|
});
|
|
180
240
|
function createEffect(model, callback, keys) {
|
|
@@ -188,7 +248,7 @@ function createEffect(model, callback, keys) {
|
|
|
188
248
|
if (unSet instanceof Promise)
|
|
189
249
|
unSet = undefined;
|
|
190
250
|
if (unSet && typeof unSet !== "function")
|
|
191
|
-
throw Oops$
|
|
251
|
+
throw Oops$a.BadCallback();
|
|
192
252
|
}
|
|
193
253
|
function invoke() {
|
|
194
254
|
if (busy)
|
|
@@ -212,10 +272,11 @@ function createEffect(model, callback, keys) {
|
|
|
212
272
|
return invoke;
|
|
213
273
|
});
|
|
214
274
|
}
|
|
215
|
-
const sub = controller
|
|
275
|
+
const sub = new Subscriber(controller, () => invoke);
|
|
216
276
|
model = sub.proxy;
|
|
217
277
|
invoke();
|
|
218
|
-
|
|
278
|
+
sub.commit();
|
|
279
|
+
return () => sub.release();
|
|
219
280
|
});
|
|
220
281
|
}
|
|
221
282
|
function createValueEffect(callback) {
|
|
@@ -231,11 +292,11 @@ function createValueEffect(callback) {
|
|
|
231
292
|
if (typeof out == "function")
|
|
232
293
|
unSet = out;
|
|
233
294
|
else
|
|
234
|
-
throw Oops$
|
|
295
|
+
throw Oops$a.BadCallback();
|
|
235
296
|
};
|
|
236
297
|
}
|
|
237
298
|
|
|
238
|
-
const Oops$
|
|
299
|
+
const Oops$9 = issues({
|
|
239
300
|
Timeout: (keys, timeout) => `No update seen for [${keys}] within ${timeout}.`,
|
|
240
301
|
KeysExpected: (key) => `Key "${key}" was expected in current update.`,
|
|
241
302
|
StrictUpdate: () => `Expected update but none in progress.`,
|
|
@@ -271,13 +332,13 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
271
332
|
const timeout = (message) => {
|
|
272
333
|
const k = keys ? keys.join(", ") : "any";
|
|
273
334
|
removeListener();
|
|
274
|
-
reject(Oops$
|
|
335
|
+
reject(Oops$9.Timeout(k, message));
|
|
275
336
|
};
|
|
276
337
|
const removeListener = control(source, controller => {
|
|
277
338
|
const pending = controller.frame;
|
|
278
339
|
if (keys === null) {
|
|
279
340
|
if (pending.size)
|
|
280
|
-
reject(Oops$
|
|
341
|
+
reject(Oops$9.StrictNoUpdate());
|
|
281
342
|
else
|
|
282
343
|
resolve(null);
|
|
283
344
|
return;
|
|
@@ -285,7 +346,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
285
346
|
if (keys) {
|
|
286
347
|
if (keys.length) {
|
|
287
348
|
if (arg2 === 0 && single && !pending.has(keys[0])) {
|
|
288
|
-
reject(Oops$
|
|
349
|
+
reject(Oops$9.KeysExpected(keys[0]));
|
|
289
350
|
return;
|
|
290
351
|
}
|
|
291
352
|
else
|
|
@@ -297,7 +358,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
297
358
|
}
|
|
298
359
|
}
|
|
299
360
|
else if (!pending.size && arg1 === true || arg2 === 0) {
|
|
300
|
-
reject(Oops$
|
|
361
|
+
reject(Oops$9.StrictUpdate());
|
|
301
362
|
return;
|
|
302
363
|
}
|
|
303
364
|
else
|
|
@@ -320,68 +381,7 @@ function awaitUpdate(source, arg1, arg2) {
|
|
|
320
381
|
});
|
|
321
382
|
}
|
|
322
383
|
|
|
323
|
-
const
|
|
324
|
-
class Subscriber {
|
|
325
|
-
constructor(parent, onUpdate, suspend) {
|
|
326
|
-
this.parent = parent;
|
|
327
|
-
this.onUpdate = onUpdate;
|
|
328
|
-
this.suspend = suspend;
|
|
329
|
-
this.active = false;
|
|
330
|
-
this.dependant = new Set();
|
|
331
|
-
this.watch = new Map();
|
|
332
|
-
const proxy = create(parent.subject);
|
|
333
|
-
const reset = () => this.latest = undefined;
|
|
334
|
-
REGISTER$1.set(proxy, this);
|
|
335
|
-
defineProperty(this, "proxy", {
|
|
336
|
-
configurable: true,
|
|
337
|
-
get() {
|
|
338
|
-
setTimeout(reset, 0);
|
|
339
|
-
return proxy;
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
get using() {
|
|
344
|
-
return Array.from(this.watch.keys());
|
|
345
|
-
}
|
|
346
|
-
add(key, value) {
|
|
347
|
-
if (value !== undefined)
|
|
348
|
-
this.watch.set(key, value);
|
|
349
|
-
else if (!this.watch.has(key))
|
|
350
|
-
this.watch.set(key, true);
|
|
351
|
-
}
|
|
352
|
-
commit() {
|
|
353
|
-
const release = this.parent.addListener(key => {
|
|
354
|
-
if (this.active)
|
|
355
|
-
this.onEvent(key);
|
|
356
|
-
});
|
|
357
|
-
this.active = true;
|
|
358
|
-
this.dependant.forEach(x => x.commit());
|
|
359
|
-
return this.release = () => {
|
|
360
|
-
this.dependant.forEach(x => x.release());
|
|
361
|
-
release();
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
onEvent(key) {
|
|
365
|
-
const { parent, watch } = this;
|
|
366
|
-
let handler = watch.get(key);
|
|
367
|
-
if (typeof handler == "function")
|
|
368
|
-
handler = handler();
|
|
369
|
-
if (handler) {
|
|
370
|
-
const notify = this.onUpdate(key, parent);
|
|
371
|
-
if (notify) {
|
|
372
|
-
parent.waiting.add(update => {
|
|
373
|
-
this.latest = update.filter(k => watch.has(k));
|
|
374
|
-
});
|
|
375
|
-
parent.waiting.add(notify);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function subscriber(from) {
|
|
381
|
-
return REGISTER$1.get(from);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const Oops$b = issues({
|
|
384
|
+
const Oops$8 = issues({
|
|
385
385
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
386
386
|
});
|
|
387
387
|
class Model {
|
|
@@ -439,7 +439,7 @@ class Model {
|
|
|
439
439
|
return {
|
|
440
440
|
then: (callback) => {
|
|
441
441
|
if (!callback)
|
|
442
|
-
throw Oops$
|
|
442
|
+
throw Oops$8.NoChaining();
|
|
443
443
|
controller.waiting.add(callback);
|
|
444
444
|
}
|
|
445
445
|
};
|
|
@@ -472,11 +472,150 @@ class Model {
|
|
|
472
472
|
maybe.prototype instanceof this);
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
|
-
defineProperty(Model.prototype, "toString", {
|
|
476
|
-
value() {
|
|
477
|
-
return this.constructor.name;
|
|
475
|
+
defineProperty(Model.prototype, "toString", {
|
|
476
|
+
value() {
|
|
477
|
+
return this.constructor.name;
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
const FindInstruction = new WeakMap([
|
|
481
|
+
[Model, getParentForGetInstruction]
|
|
482
|
+
]);
|
|
483
|
+
|
|
484
|
+
const Oops$7 = issues({
|
|
485
|
+
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or get) as computed source for ${model}.${property}. This is not allowed.`,
|
|
486
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
487
|
+
});
|
|
488
|
+
function get(arg0, arg1) {
|
|
489
|
+
return add(function get(key) {
|
|
490
|
+
const { subject, state } = this;
|
|
491
|
+
// Easy mistake, using a peer, will always be unresolved.
|
|
492
|
+
if (typeof arg0 == "symbol")
|
|
493
|
+
throw Oops$7.PeerNotAllowed(subject, key);
|
|
494
|
+
let source;
|
|
495
|
+
const sourceRequired = arg1 !== false;
|
|
496
|
+
if (arg0 instanceof Model) {
|
|
497
|
+
source = () => arg0;
|
|
498
|
+
if (typeof arg1 !== "function")
|
|
499
|
+
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
500
|
+
}
|
|
501
|
+
else if (Model.isTypeof(arg0)) {
|
|
502
|
+
source = find(arg0, subject, sourceRequired);
|
|
503
|
+
}
|
|
504
|
+
else if (typeof arg0 == "function") {
|
|
505
|
+
arg1 = arg0.call(subject, key, subject);
|
|
506
|
+
source = () => subject;
|
|
507
|
+
}
|
|
508
|
+
if (typeof arg1 == "function")
|
|
509
|
+
return getComputed(key, this, source, arg1);
|
|
510
|
+
else {
|
|
511
|
+
const init = source((got) => {
|
|
512
|
+
state.set(key, got);
|
|
513
|
+
this.update(key);
|
|
514
|
+
});
|
|
515
|
+
// TODO: remove fixes suspense test
|
|
516
|
+
if (init || arg1 === false)
|
|
517
|
+
state.set(key, init);
|
|
518
|
+
return getRecursive(key, this);
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
function getComputed(key, parent, source, setter) {
|
|
523
|
+
const { state } = parent;
|
|
524
|
+
let sub;
|
|
525
|
+
let order = ORDER.get(parent);
|
|
526
|
+
let pending = KEYS.get(parent);
|
|
527
|
+
let instance;
|
|
528
|
+
if (!order)
|
|
529
|
+
ORDER.set(parent, order = new Map());
|
|
530
|
+
if (!pending)
|
|
531
|
+
KEYS.set(parent, pending = new Set());
|
|
532
|
+
const compute = (initial) => {
|
|
533
|
+
try {
|
|
534
|
+
return setter.call(sub.proxy, sub.proxy);
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
Oops$7.Failed(instance, key, initial).warn();
|
|
538
|
+
throw err;
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
const create = () => {
|
|
542
|
+
// TODO: replace create with a cleanup function
|
|
543
|
+
const got = source(create);
|
|
544
|
+
if (!got)
|
|
545
|
+
throw suspend(parent, key);
|
|
546
|
+
instance = got;
|
|
547
|
+
sub = new Subscriber(control(instance), (_, control) => {
|
|
548
|
+
if (control !== parent)
|
|
549
|
+
refresh();
|
|
550
|
+
else
|
|
551
|
+
pending.add(refresh);
|
|
552
|
+
});
|
|
553
|
+
sub.watch.set(key, false);
|
|
554
|
+
try {
|
|
555
|
+
const value = compute(true);
|
|
556
|
+
state.set(key, value);
|
|
557
|
+
return value;
|
|
558
|
+
}
|
|
559
|
+
finally {
|
|
560
|
+
sub.commit();
|
|
561
|
+
order.set(refresh, order.size);
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
const refresh = () => {
|
|
565
|
+
let value;
|
|
566
|
+
try {
|
|
567
|
+
value = compute(false);
|
|
568
|
+
}
|
|
569
|
+
catch (e) {
|
|
570
|
+
console.error(e);
|
|
571
|
+
}
|
|
572
|
+
finally {
|
|
573
|
+
if (state.get(key) !== value) {
|
|
574
|
+
state.set(key, value);
|
|
575
|
+
parent.update(key);
|
|
576
|
+
return value;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
INFO.set(refresh, key);
|
|
581
|
+
return () => {
|
|
582
|
+
if (pending.has(refresh)) {
|
|
583
|
+
pending.delete(refresh);
|
|
584
|
+
refresh();
|
|
585
|
+
}
|
|
586
|
+
return sub ? state.get(key) : create();
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
const INFO = new WeakMap();
|
|
590
|
+
const KEYS = new WeakMap();
|
|
591
|
+
const ORDER = new WeakMap();
|
|
592
|
+
function flush(control) {
|
|
593
|
+
const pending = KEYS.get(control);
|
|
594
|
+
if (!pending || !pending.size)
|
|
595
|
+
return;
|
|
596
|
+
const priority = ORDER.get(control);
|
|
597
|
+
while (pending.size) {
|
|
598
|
+
let compute;
|
|
599
|
+
for (const item of pending)
|
|
600
|
+
if (!compute || priority.get(item) < priority.get(compute))
|
|
601
|
+
compute = item;
|
|
602
|
+
pending.delete(compute);
|
|
603
|
+
const key = INFO.get(compute);
|
|
604
|
+
if (!control.frame.has(key))
|
|
605
|
+
compute();
|
|
478
606
|
}
|
|
479
|
-
|
|
607
|
+
pending.clear();
|
|
608
|
+
}
|
|
609
|
+
// TODO: collapse this function when MVC is merged into Model.
|
|
610
|
+
function find(type, relativeTo, required) {
|
|
611
|
+
let T = type;
|
|
612
|
+
do {
|
|
613
|
+
T = getPrototypeOf(T);
|
|
614
|
+
const getter = FindInstruction.get(T);
|
|
615
|
+
if (getter)
|
|
616
|
+
return getter(type, relativeTo, required);
|
|
617
|
+
} while (T.prototype instanceof Model);
|
|
618
|
+
}
|
|
480
619
|
|
|
481
620
|
const REGISTER = new WeakMap();
|
|
482
621
|
const PENDING = new Map();
|
|
@@ -488,9 +627,6 @@ class Control {
|
|
|
488
627
|
this.followers = new Set();
|
|
489
628
|
REGISTER.set(subject, this);
|
|
490
629
|
}
|
|
491
|
-
subscribe(callback) {
|
|
492
|
-
return new Subscriber(this, callback);
|
|
493
|
-
}
|
|
494
630
|
watch(key) {
|
|
495
631
|
const { subject, state } = this;
|
|
496
632
|
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
@@ -501,7 +637,7 @@ class Control {
|
|
|
501
637
|
if (instruction) {
|
|
502
638
|
delete subject[key];
|
|
503
639
|
PENDING.delete(value);
|
|
504
|
-
instruction
|
|
640
|
+
instruction(this, key);
|
|
505
641
|
}
|
|
506
642
|
return;
|
|
507
643
|
}
|
|
@@ -517,8 +653,8 @@ class Control {
|
|
|
517
653
|
const sub = subscriber(this);
|
|
518
654
|
const value = state.get(key);
|
|
519
655
|
if (sub) {
|
|
520
|
-
sub.
|
|
521
|
-
if (value === undefined && sub.
|
|
656
|
+
sub.follow(key);
|
|
657
|
+
if (value === undefined && sub.strict)
|
|
522
658
|
throw suspend(this, key);
|
|
523
659
|
}
|
|
524
660
|
return value;
|
|
@@ -579,6 +715,8 @@ class Control {
|
|
|
579
715
|
listeners.forEach(x => x(null, this));
|
|
580
716
|
}
|
|
581
717
|
}
|
|
718
|
+
Control.get = controller;
|
|
719
|
+
Control.for = control;
|
|
582
720
|
function controller(from) {
|
|
583
721
|
if ("is" in from)
|
|
584
722
|
from = from.is;
|
|
@@ -608,68 +746,6 @@ function control(subject, cb) {
|
|
|
608
746
|
return cb ? cb(control) : control;
|
|
609
747
|
}
|
|
610
748
|
|
|
611
|
-
const Parent = new WeakMap();
|
|
612
|
-
const Oops$a = issues({
|
|
613
|
-
BadAssignment: (parent, expected, got) => `Property ${parent} expected Model of type ${expected} but got ${got}.`
|
|
614
|
-
});
|
|
615
|
-
function getRecursive(key, from) {
|
|
616
|
-
const context = new WeakMap();
|
|
617
|
-
const { state } = from;
|
|
618
|
-
return (local) => {
|
|
619
|
-
if (!local)
|
|
620
|
-
return state.get(key);
|
|
621
|
-
if (!context.has(local)) {
|
|
622
|
-
let reset;
|
|
623
|
-
const init = () => {
|
|
624
|
-
if (reset)
|
|
625
|
-
reset();
|
|
626
|
-
const value = state.get(key);
|
|
627
|
-
if (value && controller(value)) {
|
|
628
|
-
const child = control(value).subscribe(local.onUpdate);
|
|
629
|
-
if (local.active)
|
|
630
|
-
child.commit();
|
|
631
|
-
local.dependant.add(child);
|
|
632
|
-
context.set(local, child.proxy);
|
|
633
|
-
reset = () => {
|
|
634
|
-
child.release();
|
|
635
|
-
local.dependant.delete(child);
|
|
636
|
-
context.set(local, undefined);
|
|
637
|
-
reset = undefined;
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
return true;
|
|
641
|
-
};
|
|
642
|
-
local.add(key, init);
|
|
643
|
-
init();
|
|
644
|
-
}
|
|
645
|
-
return context.get(local);
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
function setRecursive(controller, key, initial) {
|
|
649
|
-
const { state, subject } = controller;
|
|
650
|
-
const Type = initial.constructor;
|
|
651
|
-
let get;
|
|
652
|
-
const onUpdate = (next) => {
|
|
653
|
-
state.set(key, next);
|
|
654
|
-
if (!(next instanceof Type))
|
|
655
|
-
throw Oops$a.BadAssignment(`${subject}.${key}`, Type.name, String(next));
|
|
656
|
-
get = getRecursive(key, controller);
|
|
657
|
-
Parent.set(next, subject);
|
|
658
|
-
control(next);
|
|
659
|
-
return true;
|
|
660
|
-
};
|
|
661
|
-
onUpdate(initial);
|
|
662
|
-
defineProperty(subject, key, {
|
|
663
|
-
set: controller.ref(key, onUpdate),
|
|
664
|
-
get() {
|
|
665
|
-
const local = subscriber(this);
|
|
666
|
-
if (local)
|
|
667
|
-
local.add(key);
|
|
668
|
-
return get(local);
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
|
|
673
749
|
/**
|
|
674
750
|
* Run instruction as controller sets itself up.
|
|
675
751
|
* This will specialize the behavior of a given property.
|
|
@@ -677,64 +753,42 @@ function setRecursive(controller, key, initial) {
|
|
|
677
753
|
function add(instruction, label) {
|
|
678
754
|
const name = label || instruction.name || "pending";
|
|
679
755
|
const placeholder = Symbol(`${name} instruction`);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
756
|
+
PENDING.set(placeholder, (control, key) => {
|
|
757
|
+
let output = instruction.call(control, key, control);
|
|
758
|
+
if (!output)
|
|
759
|
+
return undefined;
|
|
683
760
|
if (typeof output == "function")
|
|
684
761
|
output = { get: output };
|
|
685
|
-
if (typeof output != "object")
|
|
686
|
-
return;
|
|
687
|
-
if ("explicit" in output && output.explicit) {
|
|
688
|
-
defineProperty(subject, key, output);
|
|
689
|
-
return false;
|
|
690
|
-
}
|
|
691
|
-
let { get: onGet, set: onSet, suspend: shouldSuspend } = output;
|
|
692
762
|
if ("value" in output)
|
|
693
|
-
state.set(key, output.value);
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (destroy)
|
|
699
|
-
this.addListener((key) => {
|
|
700
|
-
if (key == null)
|
|
701
|
-
destroy();
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
const control = this;
|
|
705
|
-
defineProperty(subject, key, {
|
|
706
|
-
enumerable: output.enumerable,
|
|
707
|
-
set: onSet === false
|
|
763
|
+
control.state.set(key, output.value);
|
|
764
|
+
let { enumerable, get, set } = output;
|
|
765
|
+
defineProperty(control.subject, key, {
|
|
766
|
+
enumerable,
|
|
767
|
+
set: set === false
|
|
708
768
|
? undefined
|
|
709
|
-
:
|
|
769
|
+
: control.ref(key, set),
|
|
710
770
|
get() {
|
|
711
|
-
if (!state.has(key) && shouldSuspend)
|
|
712
|
-
throw suspend(control, key);
|
|
713
771
|
const local = subscriber(this);
|
|
714
|
-
const required = local && local.suspend;
|
|
715
772
|
if (local)
|
|
716
|
-
local.
|
|
773
|
+
local.follow(key);
|
|
717
774
|
try {
|
|
718
|
-
const value =
|
|
719
|
-
|
|
720
|
-
: state.get(key);
|
|
721
|
-
if (value === undefined && required === true)
|
|
775
|
+
const value = get ? get(local) : control.state.get(key);
|
|
776
|
+
if (value === undefined && local && local.strict === true)
|
|
722
777
|
throw suspend(control, key);
|
|
723
778
|
return value;
|
|
724
779
|
}
|
|
725
780
|
catch (err) {
|
|
726
|
-
if (err instanceof Promise &&
|
|
781
|
+
if (err instanceof Promise && local && local.strict === false)
|
|
727
782
|
return;
|
|
728
783
|
throw err;
|
|
729
784
|
}
|
|
730
785
|
}
|
|
731
786
|
});
|
|
732
|
-
}
|
|
733
|
-
PENDING.set(placeholder, setup);
|
|
787
|
+
});
|
|
734
788
|
return placeholder;
|
|
735
789
|
}
|
|
736
790
|
|
|
737
|
-
|
|
791
|
+
/******************************************************************************
|
|
738
792
|
Copyright (c) Microsoft Corporation.
|
|
739
793
|
|
|
740
794
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
@@ -759,7 +813,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
759
813
|
});
|
|
760
814
|
}
|
|
761
815
|
|
|
762
|
-
const Oops$
|
|
816
|
+
const Oops$6 = issues({
|
|
763
817
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
764
818
|
});
|
|
765
819
|
function run(task) {
|
|
@@ -767,7 +821,7 @@ function run(task) {
|
|
|
767
821
|
let pending = false;
|
|
768
822
|
const invoke = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
769
823
|
if (pending)
|
|
770
|
-
return Promise.reject(Oops$
|
|
824
|
+
return Promise.reject(Oops$6.DuplicatePending(key));
|
|
771
825
|
pending = true;
|
|
772
826
|
this.update(key);
|
|
773
827
|
try {
|
|
@@ -789,106 +843,6 @@ function run(task) {
|
|
|
789
843
|
});
|
|
790
844
|
}
|
|
791
845
|
|
|
792
|
-
const Oops$8 = issues({
|
|
793
|
-
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
794
|
-
});
|
|
795
|
-
function factoryMode(self, value, key, required) {
|
|
796
|
-
const { subject, state } = self;
|
|
797
|
-
let pending;
|
|
798
|
-
let error;
|
|
799
|
-
if (value instanceof Promise) {
|
|
800
|
-
state.set(key, undefined);
|
|
801
|
-
pending = value
|
|
802
|
-
.catch(err => error = err)
|
|
803
|
-
.then(val => {
|
|
804
|
-
state.set(key, val);
|
|
805
|
-
return val;
|
|
806
|
-
})
|
|
807
|
-
.finally(() => {
|
|
808
|
-
pending = undefined;
|
|
809
|
-
self.update(key);
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
else
|
|
813
|
-
state.set(key, value);
|
|
814
|
-
const suspend = () => {
|
|
815
|
-
if (required === false)
|
|
816
|
-
return undefined;
|
|
817
|
-
const issue = Oops$8.NotReady(subject, key);
|
|
818
|
-
assign(pending, {
|
|
819
|
-
message: issue.message,
|
|
820
|
-
stack: issue.stack
|
|
821
|
-
});
|
|
822
|
-
throw pending;
|
|
823
|
-
};
|
|
824
|
-
return () => {
|
|
825
|
-
if (error)
|
|
826
|
-
throw error;
|
|
827
|
-
if (pending)
|
|
828
|
-
return suspend();
|
|
829
|
-
if (state.has(key))
|
|
830
|
-
return state.get(key);
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
const Oops$7 = issues({
|
|
835
|
-
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
836
|
-
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
837
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
838
|
-
});
|
|
839
|
-
function get(arg0, arg1, arg2) {
|
|
840
|
-
return add(function get(key) {
|
|
841
|
-
const { subject } = this;
|
|
842
|
-
const computeRequired = arg1 === true || arg2 === true;
|
|
843
|
-
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
844
|
-
let getter;
|
|
845
|
-
// Easy mistake, using a peer, will always be unresolved.
|
|
846
|
-
if (typeof arg0 == "symbol")
|
|
847
|
-
throw Oops$7.PeerNotAllowed(subject, key);
|
|
848
|
-
// if(typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
849
|
-
// throw Oops.BadSource(subject, key, arg0);
|
|
850
|
-
this.state.set(key, undefined);
|
|
851
|
-
const init = () => {
|
|
852
|
-
let source = this;
|
|
853
|
-
let setter;
|
|
854
|
-
if (typeof arg0 == "function") {
|
|
855
|
-
const result = mayRetry(arg0.bind(subject, key, subject));
|
|
856
|
-
if (typeof result == "function")
|
|
857
|
-
setter = result;
|
|
858
|
-
else {
|
|
859
|
-
getter = factoryMode(this, result, key, factoryRequired);
|
|
860
|
-
return;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
else if (arg0 instanceof Promise) {
|
|
864
|
-
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
else if (typeof arg1 == "function") {
|
|
868
|
-
// replace source controller in-case it is different
|
|
869
|
-
source = control(arg0);
|
|
870
|
-
setter = arg1;
|
|
871
|
-
}
|
|
872
|
-
else
|
|
873
|
-
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
874
|
-
getter = computeMode(this, source, setter, key, computeRequired);
|
|
875
|
-
};
|
|
876
|
-
if (typeof arg0 == "function" && computeRequired)
|
|
877
|
-
try {
|
|
878
|
-
init();
|
|
879
|
-
}
|
|
880
|
-
catch (err) {
|
|
881
|
-
Oops$7.ComputeFailed(subject, key).warn();
|
|
882
|
-
throw err;
|
|
883
|
-
}
|
|
884
|
-
return () => {
|
|
885
|
-
if (!getter)
|
|
886
|
-
init();
|
|
887
|
-
return getter();
|
|
888
|
-
};
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
|
|
892
846
|
function ref(arg, mapper) {
|
|
893
847
|
return add(function ref(key) {
|
|
894
848
|
let value = {};
|
|
@@ -908,7 +862,7 @@ function ref(arg, mapper) {
|
|
|
908
862
|
value: createRef(this, key)
|
|
909
863
|
});
|
|
910
864
|
});
|
|
911
|
-
|
|
865
|
+
defineProperty(this.subject, key, { value });
|
|
912
866
|
});
|
|
913
867
|
}
|
|
914
868
|
function createRef(src, key, cb) {
|
|
@@ -920,16 +874,78 @@ function createRef(src, key, cb) {
|
|
|
920
874
|
return refObjectFunction;
|
|
921
875
|
}
|
|
922
876
|
|
|
877
|
+
const Oops$5 = issues({
|
|
878
|
+
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
879
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
880
|
+
});
|
|
923
881
|
function set(value, argument) {
|
|
924
|
-
if (!(1 in arguments)) {
|
|
925
|
-
argument = value;
|
|
926
|
-
value = undefined;
|
|
927
|
-
}
|
|
928
882
|
return add(function set(key) {
|
|
883
|
+
const { state, subject } = this;
|
|
884
|
+
if (typeof value == "function" || value instanceof Promise) {
|
|
885
|
+
const required = argument !== false;
|
|
886
|
+
let getter;
|
|
887
|
+
const init = () => {
|
|
888
|
+
try {
|
|
889
|
+
if (typeof value == "function")
|
|
890
|
+
value = mayRetry(value.bind(subject, key, subject));
|
|
891
|
+
let pending;
|
|
892
|
+
let error;
|
|
893
|
+
if (value instanceof Promise) {
|
|
894
|
+
state.set(key, undefined);
|
|
895
|
+
pending = value
|
|
896
|
+
.catch(err => error = err)
|
|
897
|
+
.then(val => {
|
|
898
|
+
state.set(key, val);
|
|
899
|
+
return val;
|
|
900
|
+
})
|
|
901
|
+
.finally(() => {
|
|
902
|
+
pending = undefined;
|
|
903
|
+
this.update(key);
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
else
|
|
907
|
+
state.set(key, value);
|
|
908
|
+
const suspend = () => {
|
|
909
|
+
if (required === false)
|
|
910
|
+
return undefined;
|
|
911
|
+
const issue = Oops$5.NotReady(subject, key);
|
|
912
|
+
assign(pending, {
|
|
913
|
+
message: issue.message,
|
|
914
|
+
stack: issue.stack
|
|
915
|
+
});
|
|
916
|
+
throw pending;
|
|
917
|
+
};
|
|
918
|
+
getter = () => {
|
|
919
|
+
if (error)
|
|
920
|
+
throw error;
|
|
921
|
+
if (pending)
|
|
922
|
+
return suspend();
|
|
923
|
+
if (state.has(key))
|
|
924
|
+
return state.get(key);
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
catch (err) {
|
|
928
|
+
Oops$5.ComputeFailed(subject, key).warn();
|
|
929
|
+
throw err;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
if (argument === true)
|
|
933
|
+
init();
|
|
934
|
+
return () => {
|
|
935
|
+
if (!getter)
|
|
936
|
+
init();
|
|
937
|
+
return getter();
|
|
938
|
+
};
|
|
939
|
+
}
|
|
929
940
|
if (value !== undefined)
|
|
930
|
-
|
|
941
|
+
state.set(key, value);
|
|
931
942
|
return {
|
|
932
|
-
|
|
943
|
+
get: () => {
|
|
944
|
+
if (state.has(key))
|
|
945
|
+
return state.get(key);
|
|
946
|
+
else
|
|
947
|
+
throw suspend(this, key);
|
|
948
|
+
},
|
|
933
949
|
set: typeof argument == "function"
|
|
934
950
|
? createValueEffect(argument)
|
|
935
951
|
: undefined
|
|
@@ -973,7 +989,7 @@ function keyed(control, property, initial) {
|
|
|
973
989
|
}
|
|
974
990
|
}
|
|
975
991
|
}
|
|
976
|
-
local.
|
|
992
|
+
local.follow(property, false);
|
|
977
993
|
local.dependant.add({
|
|
978
994
|
commit() {
|
|
979
995
|
if (using.size === 0)
|
|
@@ -989,6 +1005,12 @@ function keyed(control, property, initial) {
|
|
|
989
1005
|
context.set(local, proxy);
|
|
990
1006
|
return proxy;
|
|
991
1007
|
}
|
|
1008
|
+
control.addListener(key => {
|
|
1009
|
+
if (key === null) {
|
|
1010
|
+
update.clear();
|
|
1011
|
+
context.clear();
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
992
1014
|
return {
|
|
993
1015
|
value: initial,
|
|
994
1016
|
get(local) {
|
|
@@ -1001,10 +1023,6 @@ function keyed(control, property, initial) {
|
|
|
1001
1023
|
managed = init(next);
|
|
1002
1024
|
context.clear();
|
|
1003
1025
|
emit(ANY);
|
|
1004
|
-
},
|
|
1005
|
-
destroy() {
|
|
1006
|
-
update.clear();
|
|
1007
|
-
context.clear();
|
|
1008
1026
|
}
|
|
1009
1027
|
};
|
|
1010
1028
|
}
|
|
@@ -1083,11 +1101,11 @@ function createProxy(emit, watch) {
|
|
|
1083
1101
|
};
|
|
1084
1102
|
}
|
|
1085
1103
|
|
|
1086
|
-
const Oops$
|
|
1104
|
+
const Oops$4 = issues({
|
|
1087
1105
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1088
1106
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1089
1107
|
});
|
|
1090
|
-
function use
|
|
1108
|
+
function use(input, argument) {
|
|
1091
1109
|
return add(function use(key) {
|
|
1092
1110
|
const { state, subject } = this;
|
|
1093
1111
|
const required = argument !== false;
|
|
@@ -1099,7 +1117,7 @@ function use$1(input, argument) {
|
|
|
1099
1117
|
input = new input();
|
|
1100
1118
|
}
|
|
1101
1119
|
else if (input && typeof input !== "object")
|
|
1102
|
-
throw Oops$
|
|
1120
|
+
throw Oops$4.BadArgument(typeof input);
|
|
1103
1121
|
if (input instanceof Map || input instanceof Set)
|
|
1104
1122
|
return keyed(this, key, input);
|
|
1105
1123
|
const onUpdate = (next) => {
|
|
@@ -1116,7 +1134,7 @@ function use$1(input, argument) {
|
|
|
1116
1134
|
const suspend = () => {
|
|
1117
1135
|
if (required === false)
|
|
1118
1136
|
return;
|
|
1119
|
-
const issue = Oops$
|
|
1137
|
+
const issue = Oops$4.NotReady(subject, key);
|
|
1120
1138
|
assign(pending, {
|
|
1121
1139
|
message: issue.message,
|
|
1122
1140
|
stack: issue.stack
|
|
@@ -1161,33 +1179,11 @@ function use$1(input, argument) {
|
|
|
1161
1179
|
});
|
|
1162
1180
|
}
|
|
1163
1181
|
|
|
1164
|
-
|
|
1165
|
-
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1166
|
-
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1167
|
-
});
|
|
1168
|
-
function has(Type, required) {
|
|
1169
|
-
return add(function parent() {
|
|
1170
|
-
const child = this.subject;
|
|
1171
|
-
const value = Parent.get(child);
|
|
1172
|
-
const expected = Type.name;
|
|
1173
|
-
if (!value) {
|
|
1174
|
-
if (required !== false)
|
|
1175
|
-
throw Oops$5.Required(expected, child);
|
|
1176
|
-
}
|
|
1177
|
-
else if (!(value instanceof Type))
|
|
1178
|
-
throw Oops$5.Unexpected(expected, child, value);
|
|
1179
|
-
return { value };
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
const Oops$4 = issues({
|
|
1184
|
-
NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`
|
|
1185
|
-
});
|
|
1186
|
-
class Lookup {
|
|
1182
|
+
class Register {
|
|
1187
1183
|
constructor() {
|
|
1188
1184
|
this.table = new Map();
|
|
1189
1185
|
}
|
|
1190
|
-
|
|
1186
|
+
has(T) {
|
|
1191
1187
|
let key = this.table.get(T);
|
|
1192
1188
|
if (!key) {
|
|
1193
1189
|
key = Symbol(T.name);
|
|
@@ -1196,22 +1192,9 @@ class Lookup {
|
|
|
1196
1192
|
return key;
|
|
1197
1193
|
}
|
|
1198
1194
|
get(Type) {
|
|
1199
|
-
return this[this.
|
|
1200
|
-
}
|
|
1201
|
-
has(key, input, callback) {
|
|
1202
|
-
if (MVC.isTypeof(input) && input.global)
|
|
1203
|
-
return input.new();
|
|
1204
|
-
if (this.register.get(key) === input)
|
|
1205
|
-
return typeof input == "object"
|
|
1206
|
-
? input
|
|
1207
|
-
: this.get(input);
|
|
1208
|
-
const instance = this.add(input);
|
|
1209
|
-
this.register.set(key, input);
|
|
1210
|
-
if (callback)
|
|
1211
|
-
callback(instance);
|
|
1212
|
-
return instance;
|
|
1195
|
+
return this[this.has(Type)];
|
|
1213
1196
|
}
|
|
1214
|
-
add(input) {
|
|
1197
|
+
add(input, key) {
|
|
1215
1198
|
let writable = true;
|
|
1216
1199
|
let T;
|
|
1217
1200
|
let I;
|
|
@@ -1220,19 +1203,21 @@ class Lookup {
|
|
|
1220
1203
|
I = new input();
|
|
1221
1204
|
}
|
|
1222
1205
|
else {
|
|
1223
|
-
I = input;
|
|
1206
|
+
I = input.is;
|
|
1224
1207
|
T = I.constructor;
|
|
1225
1208
|
writable = false;
|
|
1226
1209
|
}
|
|
1227
1210
|
do {
|
|
1228
|
-
const key = this.
|
|
1211
|
+
const key = this.has(T);
|
|
1229
1212
|
defineProperty(this, key, {
|
|
1230
1213
|
configurable: true,
|
|
1231
|
-
value: this.hasOwnProperty(key) ? null : I,
|
|
1214
|
+
value: this.hasOwnProperty(key) && I !== this[key] ? null : I,
|
|
1232
1215
|
writable
|
|
1233
1216
|
});
|
|
1234
1217
|
T = getPrototypeOf(T);
|
|
1235
1218
|
} while (T !== Model);
|
|
1219
|
+
if (key !== undefined)
|
|
1220
|
+
this.register.set(key, input);
|
|
1236
1221
|
return I;
|
|
1237
1222
|
}
|
|
1238
1223
|
push() {
|
|
@@ -1246,52 +1231,77 @@ class Lookup {
|
|
|
1246
1231
|
const entry = getOwnPropertyDescriptor(this, key);
|
|
1247
1232
|
if (entry.writable && entry.value)
|
|
1248
1233
|
items.add(entry.value);
|
|
1234
|
+
delete this[key];
|
|
1249
1235
|
}
|
|
1250
1236
|
for (const model of items)
|
|
1251
1237
|
model.end();
|
|
1252
1238
|
}
|
|
1239
|
+
delete(instance) {
|
|
1240
|
+
for (const key of getOwnPropertySymbols(this)) {
|
|
1241
|
+
const entry = getOwnPropertyDescriptor(this, key);
|
|
1242
|
+
if (entry.value === instance)
|
|
1243
|
+
delete this[key];
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
const Global$1 = new Register();
|
|
1248
|
+
|
|
1249
|
+
const Oops$3 = issues({
|
|
1250
|
+
AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`,
|
|
1251
|
+
DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.new() before attempting to access, or consider using ${name}.use() instead.`,
|
|
1252
|
+
NotFound: (name) => `Couldn't find ${name} in context; did you forget to use a Provider?`,
|
|
1253
|
+
MultipleExist: (name) => `Did find ${name} in context, but multiple were defined by same Provider.`
|
|
1254
|
+
});
|
|
1255
|
+
const LookupContext = React__default["default"].createContext(Global$1);
|
|
1256
|
+
function useLookup() {
|
|
1257
|
+
try {
|
|
1258
|
+
return React__default["default"].useContext(LookupContext);
|
|
1259
|
+
}
|
|
1260
|
+
catch (err) {
|
|
1261
|
+
return Global$1;
|
|
1262
|
+
}
|
|
1253
1263
|
}
|
|
1254
|
-
const LookupContext = React__default["default"].createContext(new Lookup());
|
|
1255
|
-
const useLookup = () => React__default["default"].useContext(LookupContext);
|
|
1256
1264
|
function useContext(Type, required) {
|
|
1257
1265
|
const instance = useLookup().get(Type);
|
|
1266
|
+
if (instance === null)
|
|
1267
|
+
throw Oops$3.MultipleExist(Type.name);
|
|
1258
1268
|
if (!instance && required !== false)
|
|
1259
|
-
throw
|
|
1269
|
+
throw MVC.isTypeof(Type) && Type.global
|
|
1270
|
+
? Oops$3.DoesNotExist(Type.name)
|
|
1271
|
+
: Oops$3.NotFound(Type.name);
|
|
1260
1272
|
return instance;
|
|
1261
1273
|
}
|
|
1262
1274
|
|
|
1263
|
-
const Oops$
|
|
1275
|
+
const Oops$2 = issues({
|
|
1264
1276
|
NotAllowed: (parent, child) => `Global '${parent}' attempted to attach '${child}' but it is not also a singleton.`,
|
|
1265
|
-
AmbientRequired: (requested, requester
|
|
1277
|
+
AmbientRequired: (requested, requester) => `Attempted to find an instance of ${requested} in context. It is required by ${requester}, but one could not be found.`
|
|
1266
1278
|
});
|
|
1267
1279
|
const Pending = new WeakMap();
|
|
1268
1280
|
const Applied = new WeakMap();
|
|
1269
|
-
function
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
throw Oops$3.NotAllowed(subject, type.name);
|
|
1279
|
-
getPending(subject).push(context => {
|
|
1280
|
-
let instance = context.get(type);
|
|
1281
|
-
if (typeof argument == "function") {
|
|
1282
|
-
if (argument(instance) === false)
|
|
1283
|
-
instance = undefined;
|
|
1281
|
+
function getContextForGetInstruction(type, relativeTo, required) {
|
|
1282
|
+
let item = getParent(type, relativeTo);
|
|
1283
|
+
return (refresh) => {
|
|
1284
|
+
if (item)
|
|
1285
|
+
return item;
|
|
1286
|
+
findRelative(relativeTo, type, got => {
|
|
1287
|
+
if (got) {
|
|
1288
|
+
item = got;
|
|
1289
|
+
refresh(got);
|
|
1284
1290
|
}
|
|
1285
|
-
else if (
|
|
1286
|
-
throw Oops$
|
|
1287
|
-
|
|
1288
|
-
|
|
1291
|
+
else if (required)
|
|
1292
|
+
throw Oops$2.AmbientRequired(type.name, relativeTo);
|
|
1293
|
+
});
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
function findRelative(from, type, callback) {
|
|
1297
|
+
if (MVC.isTypeof(type) && type.global)
|
|
1298
|
+
callback(Global$1.get(type));
|
|
1299
|
+
else if (from.constructor.global)
|
|
1300
|
+
throw Oops$2.NotAllowed(from, type.name);
|
|
1301
|
+
else
|
|
1302
|
+
getPending(from).push(context => {
|
|
1303
|
+
callback(context.get(type));
|
|
1289
1304
|
});
|
|
1290
|
-
return {
|
|
1291
|
-
recursive: true,
|
|
1292
|
-
suspend: true
|
|
1293
|
-
};
|
|
1294
|
-
});
|
|
1295
1305
|
}
|
|
1296
1306
|
function usePeerContext(subject) {
|
|
1297
1307
|
if (Applied.has(subject)) {
|
|
@@ -1315,7 +1325,7 @@ function getPending(subject) {
|
|
|
1315
1325
|
return pending;
|
|
1316
1326
|
}
|
|
1317
1327
|
|
|
1318
|
-
function
|
|
1328
|
+
function useModel(source, arg1, arg2) {
|
|
1319
1329
|
const instance = React__default["default"].useMemo(() => {
|
|
1320
1330
|
const callback = arg2 || arg1;
|
|
1321
1331
|
const instance = Model.isTypeof(source)
|
|
@@ -1328,7 +1338,7 @@ function useNew(source, arg1, arg2) {
|
|
|
1328
1338
|
}, []);
|
|
1329
1339
|
usePeerContext(instance);
|
|
1330
1340
|
if (Array.isArray(arg1)) {
|
|
1331
|
-
const update =
|
|
1341
|
+
const update = React__default["default"].useState(0)[1];
|
|
1332
1342
|
React__default["default"].useLayoutEffect(() => {
|
|
1333
1343
|
if (arg1.length && instance instanceof Model)
|
|
1334
1344
|
instance.on(arg1, () => update(x => x + 1));
|
|
@@ -1342,19 +1352,10 @@ function useNew(source, arg1, arg2) {
|
|
|
1342
1352
|
const state = React__default["default"].useState(0);
|
|
1343
1353
|
const local = React__default["default"].useMemo(() => {
|
|
1344
1354
|
const refresh = state[1].bind(null, x => x + 1);
|
|
1345
|
-
return control(instance)
|
|
1355
|
+
return new Subscriber(control(instance), () => refresh);
|
|
1346
1356
|
}, []);
|
|
1347
|
-
if (typeof arg1 == "object")
|
|
1348
|
-
|
|
1349
|
-
let keys = arg2;
|
|
1350
|
-
local.active = false;
|
|
1351
|
-
if (!keys)
|
|
1352
|
-
keys = getOwnPropertyNames(subject);
|
|
1353
|
-
for (const key of keys)
|
|
1354
|
-
if (key in arg1)
|
|
1355
|
-
subject[key] = arg1[key];
|
|
1356
|
-
waiting.add(() => local.active = true);
|
|
1357
|
-
}
|
|
1357
|
+
if (typeof arg1 == "object")
|
|
1358
|
+
local.apply(arg1, arg2);
|
|
1358
1359
|
React__default["default"].useLayoutEffect(() => {
|
|
1359
1360
|
local.commit();
|
|
1360
1361
|
return () => {
|
|
@@ -1366,19 +1367,22 @@ function useNew(source, arg1, arg2) {
|
|
|
1366
1367
|
return local.proxy;
|
|
1367
1368
|
}
|
|
1368
1369
|
|
|
1369
|
-
function
|
|
1370
|
+
function useTap(source, arg1, arg2) {
|
|
1371
|
+
const instance = typeof source == "object"
|
|
1372
|
+
? source
|
|
1373
|
+
: "get" in source
|
|
1374
|
+
? source.get()
|
|
1375
|
+
: source();
|
|
1376
|
+
const deps = [uid(instance)];
|
|
1370
1377
|
const state = React__default["default"].useState(0);
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
const deps = [uid(source)];
|
|
1378
|
-
const local = use(refresh => {
|
|
1379
|
-
const sub = control(source).subscribe(() => update);
|
|
1378
|
+
const local = React__default["default"].useMemo(() => {
|
|
1379
|
+
const refresh = state[1].bind(null, x => x + 1);
|
|
1380
|
+
const controller = control(instance);
|
|
1381
|
+
if (typeof arg1 != "function")
|
|
1382
|
+
return new Subscriber(controller, () => refresh, arg1);
|
|
1383
|
+
const sub = new Subscriber(controller, () => update);
|
|
1380
1384
|
const spy = sub.proxy;
|
|
1381
|
-
let make = () =>
|
|
1385
|
+
let make = () => arg1.call(spy, spy, forceUpdate);
|
|
1382
1386
|
function forceUpdate(passthru) {
|
|
1383
1387
|
if (typeof passthru == "function")
|
|
1384
1388
|
passthru = passthru();
|
|
@@ -1409,7 +1413,7 @@ function useCompute(source, compute, suspend) {
|
|
|
1409
1413
|
if (typeof value == "function") {
|
|
1410
1414
|
const get = value;
|
|
1411
1415
|
sub.watch.clear();
|
|
1412
|
-
|
|
1416
|
+
arg1 = () => get();
|
|
1413
1417
|
value = get();
|
|
1414
1418
|
}
|
|
1415
1419
|
if (value instanceof Promise) {
|
|
@@ -1428,7 +1432,7 @@ function useCompute(source, compute, suspend) {
|
|
|
1428
1432
|
get() {
|
|
1429
1433
|
if (value !== undefined)
|
|
1430
1434
|
return value;
|
|
1431
|
-
if (
|
|
1435
|
+
if (arg2)
|
|
1432
1436
|
throw new Promise(res => retry = res);
|
|
1433
1437
|
return null;
|
|
1434
1438
|
}
|
|
@@ -1437,7 +1441,10 @@ function useCompute(source, compute, suspend) {
|
|
|
1437
1441
|
}, deps);
|
|
1438
1442
|
if (!local)
|
|
1439
1443
|
return null;
|
|
1440
|
-
React__default["default"].useLayoutEffect(() =>
|
|
1444
|
+
React__default["default"].useLayoutEffect(() => {
|
|
1445
|
+
local.commit();
|
|
1446
|
+
return () => local.release();
|
|
1447
|
+
}, deps);
|
|
1441
1448
|
return local.proxy;
|
|
1442
1449
|
}
|
|
1443
1450
|
/** Values are not equal for purposes of a refresh. */
|
|
@@ -1446,58 +1453,35 @@ const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
|
1446
1453
|
a.length !== b.length ||
|
|
1447
1454
|
a.some((x, i) => x !== b[i])));
|
|
1448
1455
|
|
|
1449
|
-
function useTap(source, arg1, arg2) {
|
|
1450
|
-
const instance = typeof source == "object"
|
|
1451
|
-
? source
|
|
1452
|
-
: "get" in source
|
|
1453
|
-
? source.get()
|
|
1454
|
-
: useContext(source);
|
|
1455
|
-
return typeof arg1 == "function"
|
|
1456
|
-
? useCompute(instance, arg1, arg2)
|
|
1457
|
-
: useSubscribe(instance, arg1);
|
|
1458
|
-
}
|
|
1459
|
-
function useSubscribe(source, expect) {
|
|
1460
|
-
const deps = [uid(source)];
|
|
1461
|
-
const local = use(refresh => (new Subscriber(control(source), () => refresh, expect)), deps);
|
|
1462
|
-
React__default["default"].useLayoutEffect(() => local.commit(), deps);
|
|
1463
|
-
return local.proxy;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
const Global$1 = new WeakMap();
|
|
1467
|
-
const Oops$2 = issues({
|
|
1468
|
-
DoesNotExist: (name) => `Tried to access singleton ${name}, but none exist! Did you forget to initialize?\nCall ${name}.new() before attempting to access, or consider using ${name}.use() instead.`,
|
|
1469
|
-
AlreadyExists: (name) => `Shared instance of ${name} already exists! Consider unmounting existing, or use ${name}.reset() to force-delete it.`
|
|
1470
|
-
});
|
|
1471
1456
|
class MVC extends Model {
|
|
1472
1457
|
end(force) {
|
|
1473
1458
|
const type = this.constructor;
|
|
1474
1459
|
if (type.keepAlive && !force)
|
|
1475
1460
|
return false;
|
|
1476
1461
|
super.end();
|
|
1477
|
-
Global$1.delete(
|
|
1462
|
+
Global$1.delete(this);
|
|
1478
1463
|
return true;
|
|
1479
1464
|
}
|
|
1480
1465
|
static new(...args) {
|
|
1481
|
-
|
|
1466
|
+
const exists = Global$1.get(this);
|
|
1467
|
+
if (exists)
|
|
1482
1468
|
if (this.keepAlive)
|
|
1483
|
-
return
|
|
1469
|
+
return exists;
|
|
1484
1470
|
else
|
|
1485
|
-
throw Oops$
|
|
1471
|
+
throw Oops$3.AlreadyExists(this.name);
|
|
1486
1472
|
const instance = super.new(...args);
|
|
1487
1473
|
if (this.global)
|
|
1488
|
-
Global$1.
|
|
1474
|
+
Global$1.add(instance);
|
|
1489
1475
|
return instance;
|
|
1490
1476
|
}
|
|
1491
1477
|
static get(arg1, arg2) {
|
|
1492
|
-
let instance;
|
|
1493
1478
|
const required = arg1 === undefined || arg1 === true;
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
instance = useContext(this, required);
|
|
1479
|
+
const instance = useContext(this, required);
|
|
1480
|
+
if (typeof arg1 === "function" && instance)
|
|
1481
|
+
callback(arg1);
|
|
1482
|
+
else if (arg2)
|
|
1483
|
+
callback(arg2);
|
|
1484
|
+
return instance;
|
|
1501
1485
|
function callback(effect) {
|
|
1502
1486
|
try {
|
|
1503
1487
|
React__default["default"].useLayoutEffect(() => effect(instance), []);
|
|
@@ -1509,29 +1493,18 @@ class MVC extends Model {
|
|
|
1509
1493
|
effect(undefined);
|
|
1510
1494
|
}
|
|
1511
1495
|
}
|
|
1512
|
-
if (typeof arg1 === "string")
|
|
1513
|
-
return instance[arg1];
|
|
1514
|
-
if (typeof arg1 === "function" && instance)
|
|
1515
|
-
callback(arg1);
|
|
1516
|
-
else if (arg2)
|
|
1517
|
-
callback(arg2);
|
|
1518
|
-
return instance;
|
|
1519
1496
|
}
|
|
1520
1497
|
static tap(arg1, arg2) {
|
|
1521
|
-
|
|
1522
|
-
return typeof arg1 == "function"
|
|
1523
|
-
? useCompute(instance, arg1, arg2)
|
|
1524
|
-
: useSubscribe(instance, arg1);
|
|
1498
|
+
return useTap(this, arg1, arg2);
|
|
1525
1499
|
}
|
|
1526
1500
|
static use(a, b) {
|
|
1527
|
-
return
|
|
1501
|
+
return useModel(this, a, b);
|
|
1528
1502
|
}
|
|
1529
1503
|
static meta(arg1, arg2) {
|
|
1530
|
-
return
|
|
1531
|
-
? useCompute(this, arg1, arg2)
|
|
1532
|
-
: useSubscribe(this, arg1);
|
|
1504
|
+
return useTap(() => this, arg1, arg2);
|
|
1533
1505
|
}
|
|
1534
|
-
}
|
|
1506
|
+
}
|
|
1507
|
+
FindInstruction.set(MVC, getContextForGetInstruction);
|
|
1535
1508
|
|
|
1536
1509
|
const Oops$1 = issues({
|
|
1537
1510
|
BadProps: () => `Provider expects either a render function, 'get' or 'has' props.`
|
|
@@ -1565,8 +1538,17 @@ function useNewContext(include, assign) {
|
|
|
1565
1538
|
throw Oops.NoType();
|
|
1566
1539
|
return ambient.push();
|
|
1567
1540
|
}, []);
|
|
1568
|
-
function register(key,
|
|
1569
|
-
|
|
1541
|
+
function register(key, input) {
|
|
1542
|
+
let instance;
|
|
1543
|
+
if (MVC.isTypeof(input) && input.global)
|
|
1544
|
+
instance = input.new();
|
|
1545
|
+
else if (context.register.get(key) === input)
|
|
1546
|
+
instance = typeof input == "object"
|
|
1547
|
+
? input
|
|
1548
|
+
: context.get(input);
|
|
1549
|
+
else
|
|
1550
|
+
instance = context.add(input, key);
|
|
1551
|
+
init.add(instance);
|
|
1570
1552
|
if (assign)
|
|
1571
1553
|
assignWeak(instance, assign);
|
|
1572
1554
|
}
|
|
@@ -1576,6 +1558,7 @@ function useNewContext(include, assign) {
|
|
|
1576
1558
|
entries(include).forEach(e => register(...e));
|
|
1577
1559
|
for (const instance of init) {
|
|
1578
1560
|
control(instance).state.forEach(value => {
|
|
1561
|
+
// TODO: should this run repeatedly?
|
|
1579
1562
|
if (Parent.get(value) === instance) {
|
|
1580
1563
|
context.add(value);
|
|
1581
1564
|
init.add(value);
|
|
@@ -1583,6 +1566,8 @@ function useNewContext(include, assign) {
|
|
|
1583
1566
|
});
|
|
1584
1567
|
for (const apply of getPending(instance))
|
|
1585
1568
|
apply(context);
|
|
1569
|
+
// TODO: add test to validate this.
|
|
1570
|
+
init.delete(instance);
|
|
1586
1571
|
}
|
|
1587
1572
|
React__default["default"].useLayoutEffect(() => () => context.pop(), []);
|
|
1588
1573
|
return context;
|
|
@@ -1638,12 +1623,7 @@ exports.Provider = Provider;
|
|
|
1638
1623
|
exports.add = add;
|
|
1639
1624
|
exports["default"] = MVC;
|
|
1640
1625
|
exports.get = get;
|
|
1641
|
-
exports.has = has;
|
|
1642
1626
|
exports.ref = ref;
|
|
1643
1627
|
exports.run = run;
|
|
1644
1628
|
exports.set = set;
|
|
1645
|
-
exports.
|
|
1646
|
-
exports.use = use$1;
|
|
1647
|
-
exports.useContext = useContext;
|
|
1648
|
-
exports.useNew = useNew;
|
|
1649
|
-
exports.useTap = useTap;
|
|
1629
|
+
exports.use = use;
|