@expressive/mvc 0.4.7 → 0.6.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 +76 -91
- package/lib/index.esm.js +589 -604
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +589 -607
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -8,31 +8,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
10
|
|
|
11
|
-
/*! *****************************************************************************
|
|
12
|
-
Copyright (c) Microsoft Corporation.
|
|
13
|
-
|
|
14
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
15
|
-
purpose with or without fee is hereby granted.
|
|
16
|
-
|
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
18
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
19
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
20
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
21
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
22
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
23
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
24
|
-
***************************************************************************** */
|
|
25
|
-
|
|
26
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
27
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
28
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
29
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
30
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
31
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
32
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
11
|
class Issue extends Error {
|
|
37
12
|
constructor() {
|
|
38
13
|
super(...arguments);
|
|
@@ -95,22 +70,95 @@ function mayRetry(fn) {
|
|
|
95
70
|
}
|
|
96
71
|
|
|
97
72
|
const Oops$b = issues({
|
|
98
|
-
|
|
73
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
99
74
|
});
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
75
|
+
const INFO = new WeakMap();
|
|
76
|
+
const KEYS = new WeakMap();
|
|
77
|
+
const ORDER = new WeakMap();
|
|
78
|
+
function computeMode(self, source, setter, key, required) {
|
|
79
|
+
const { subject, state } = self;
|
|
80
|
+
let sub;
|
|
81
|
+
let order = ORDER.get(self);
|
|
82
|
+
if (!order)
|
|
83
|
+
ORDER.set(self, order = []);
|
|
84
|
+
const compute = (initial) => {
|
|
85
|
+
try {
|
|
86
|
+
return setter.call(sub.proxy, sub.proxy);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
Oops$b.Failed(subject, key, initial).warn();
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const refresh = () => {
|
|
94
|
+
let value;
|
|
95
|
+
try {
|
|
96
|
+
value = compute(false);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.error(e);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
if (state.get(key) !== value) {
|
|
103
|
+
state.set(key, value);
|
|
104
|
+
self.update(key);
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const update = (_key, source) => {
|
|
110
|
+
if (source !== self) {
|
|
111
|
+
refresh();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
let pending = KEYS.get(self);
|
|
115
|
+
if (!pending)
|
|
116
|
+
KEYS.set(self, pending = []);
|
|
117
|
+
pending.push(refresh);
|
|
118
|
+
};
|
|
119
|
+
const create = () => {
|
|
120
|
+
sub = source.subscribe(update);
|
|
121
|
+
try {
|
|
122
|
+
const value = compute(true);
|
|
123
|
+
state.set(key, value);
|
|
110
124
|
return value;
|
|
111
125
|
}
|
|
112
|
-
|
|
126
|
+
catch (e) {
|
|
127
|
+
throw e;
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
sub.commit();
|
|
131
|
+
order.push(refresh);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
INFO.set(refresh, key);
|
|
135
|
+
return () => {
|
|
136
|
+
const value = sub ? state.get(key) : create();
|
|
137
|
+
if (value === undefined && required)
|
|
138
|
+
throw suspend(self, key);
|
|
139
|
+
return value;
|
|
140
|
+
};
|
|
113
141
|
}
|
|
142
|
+
function flush(control) {
|
|
143
|
+
const pending = KEYS.get(control);
|
|
144
|
+
if (!pending)
|
|
145
|
+
return;
|
|
146
|
+
const list = ORDER.get(control);
|
|
147
|
+
while (pending.length) {
|
|
148
|
+
const compute = pending
|
|
149
|
+
.sort((a, b) => list.indexOf(b) - list.indexOf(a))
|
|
150
|
+
.pop();
|
|
151
|
+
const key = INFO.get(compute);
|
|
152
|
+
if (!control.frame.has(key))
|
|
153
|
+
compute();
|
|
154
|
+
}
|
|
155
|
+
KEYS.delete(control);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const Oops$a = issues({
|
|
159
|
+
BadCallback: () => `Callback for effect-callback may only return a function.`
|
|
160
|
+
});
|
|
161
|
+
const { assign, create, defineProperty, entries, getPrototypeOf, getOwnPropertyNames, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
|
|
114
162
|
function createEffect(callback) {
|
|
115
163
|
let unSet;
|
|
116
164
|
return function (value) {
|
|
@@ -120,7 +168,7 @@ function createEffect(callback) {
|
|
|
120
168
|
if (unSet instanceof Promise)
|
|
121
169
|
unSet = undefined;
|
|
122
170
|
if (unSet && typeof unSet !== "function")
|
|
123
|
-
throw Oops$
|
|
171
|
+
throw Oops$a.BadCallback();
|
|
124
172
|
};
|
|
125
173
|
}
|
|
126
174
|
function createValueEffect(callback) {
|
|
@@ -136,321 +184,41 @@ function createValueEffect(callback) {
|
|
|
136
184
|
if (typeof out == "function")
|
|
137
185
|
unSet = out;
|
|
138
186
|
else
|
|
139
|
-
throw Oops$
|
|
187
|
+
throw Oops$a.BadCallback();
|
|
140
188
|
};
|
|
141
189
|
}
|
|
142
190
|
|
|
143
|
-
function ensure(subject, cb) {
|
|
144
|
-
let control = subject[CONTROL];
|
|
145
|
-
if (!control) {
|
|
146
|
-
control = new Controller(subject);
|
|
147
|
-
define(subject, CONTROL, control);
|
|
148
|
-
}
|
|
149
|
-
if (!control.state) {
|
|
150
|
-
const { waiting } = control;
|
|
151
|
-
if (cb) {
|
|
152
|
-
let done;
|
|
153
|
-
waiting.add(() => {
|
|
154
|
-
done = cb(control);
|
|
155
|
-
});
|
|
156
|
-
return () => done && done();
|
|
157
|
-
}
|
|
158
|
-
control.state = new Map();
|
|
159
|
-
for (const key in subject)
|
|
160
|
-
control.add(key);
|
|
161
|
-
const callback = Array.from(waiting);
|
|
162
|
-
waiting.clear();
|
|
163
|
-
for (const cb of callback)
|
|
164
|
-
cb();
|
|
165
|
-
}
|
|
166
|
-
return cb ? cb(control) : control;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const Oops$a = issues({
|
|
170
|
-
BadSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
171
|
-
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
172
|
-
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
173
|
-
});
|
|
174
|
-
const INFO = new WeakMap();
|
|
175
|
-
const KEYS = new WeakMap();
|
|
176
|
-
const ORDER = new WeakMap();
|
|
177
|
-
function get(source, arg1, arg2) {
|
|
178
|
-
return apply(function from(key) {
|
|
179
|
-
const { subject, state } = this;
|
|
180
|
-
const required = arg2 === true || arg1 === true;
|
|
181
|
-
let getSource;
|
|
182
|
-
if (typeof arg1 == "boolean")
|
|
183
|
-
arg1 = undefined;
|
|
184
|
-
// Easy mistake, using a peer, will always be unresolved.
|
|
185
|
-
if (typeof source == "symbol")
|
|
186
|
-
throw Oops$a.PeerNotAllowed(subject, key);
|
|
187
|
-
// replace source controller in-case it is different
|
|
188
|
-
if (typeof source == "object")
|
|
189
|
-
getSource = () => ensure(source);
|
|
190
|
-
// specifically an arrow function (getter factory)
|
|
191
|
-
else if (!source.prototype) {
|
|
192
|
-
arg1 = source.call(subject, key);
|
|
193
|
-
getSource = () => this;
|
|
194
|
-
}
|
|
195
|
-
// Regular function is too ambiguous so not allowed.
|
|
196
|
-
else
|
|
197
|
-
throw Oops$a.BadSource(subject, key, source);
|
|
198
|
-
const setter = arg1;
|
|
199
|
-
const info = { key, parent: this };
|
|
200
|
-
let sub;
|
|
201
|
-
let order = ORDER.get(this);
|
|
202
|
-
if (!order)
|
|
203
|
-
ORDER.set(this, order = []);
|
|
204
|
-
state.set(key, undefined);
|
|
205
|
-
const compute = (initial) => {
|
|
206
|
-
try {
|
|
207
|
-
return setter.call(sub.proxy, sub.proxy);
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
Oops$a.Failed(subject, key, initial).warn();
|
|
211
|
-
throw err;
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
const refreshValue = () => {
|
|
215
|
-
let value;
|
|
216
|
-
try {
|
|
217
|
-
value = compute(false);
|
|
218
|
-
}
|
|
219
|
-
catch (e) {
|
|
220
|
-
console.error(e);
|
|
221
|
-
}
|
|
222
|
-
finally {
|
|
223
|
-
if (state.get(key) !== value) {
|
|
224
|
-
state.set(key, value);
|
|
225
|
-
this.update(key);
|
|
226
|
-
return value;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
const dependancyDidUpdate = (_key, source) => {
|
|
231
|
-
if (source !== this) {
|
|
232
|
-
refreshValue();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
let pending = KEYS.get(this);
|
|
236
|
-
if (!pending)
|
|
237
|
-
KEYS.set(this, pending = []);
|
|
238
|
-
pending.push(refreshValue);
|
|
239
|
-
};
|
|
240
|
-
const create = () => {
|
|
241
|
-
const control = getSource();
|
|
242
|
-
sub = control.subscribe(dependancyDidUpdate);
|
|
243
|
-
try {
|
|
244
|
-
const value = compute(true);
|
|
245
|
-
state.set(key, value);
|
|
246
|
-
return value;
|
|
247
|
-
}
|
|
248
|
-
catch (e) {
|
|
249
|
-
throw e;
|
|
250
|
-
}
|
|
251
|
-
finally {
|
|
252
|
-
sub.commit();
|
|
253
|
-
order.push(refreshValue);
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
INFO.set(refreshValue, info);
|
|
257
|
-
return () => {
|
|
258
|
-
const value = sub ? state.get(key) : create();
|
|
259
|
-
if (value === undefined && required)
|
|
260
|
-
throw suspend(this, key);
|
|
261
|
-
return value;
|
|
262
|
-
};
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
function flush(control) {
|
|
266
|
-
const pending = KEYS.get(control);
|
|
267
|
-
if (!pending)
|
|
268
|
-
return;
|
|
269
|
-
const list = ORDER.get(control);
|
|
270
|
-
while (pending.length) {
|
|
271
|
-
const compute = pending
|
|
272
|
-
.sort((a, b) => list.indexOf(b) - list.indexOf(a))
|
|
273
|
-
.pop();
|
|
274
|
-
const { key } = INFO.get(compute);
|
|
275
|
-
if (!control.frame.has(key))
|
|
276
|
-
compute();
|
|
277
|
-
}
|
|
278
|
-
KEYS.delete(control);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
class Subscriber {
|
|
282
|
-
constructor(parent, onUpdate) {
|
|
283
|
-
this.onUpdate = onUpdate;
|
|
284
|
-
this.active = false;
|
|
285
|
-
this.dependant = new Set();
|
|
286
|
-
const proxy = create(parent.subject);
|
|
287
|
-
const using = new Map();
|
|
288
|
-
define(proxy, LOCAL, this);
|
|
289
|
-
defineProperty(this, "proxy", {
|
|
290
|
-
configurable: true,
|
|
291
|
-
get() {
|
|
292
|
-
if (UPDATE.has(proxy))
|
|
293
|
-
setTimeout(() => UPDATE.delete(proxy), 0);
|
|
294
|
-
return proxy;
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
const release = parent.addListener(key => {
|
|
298
|
-
if (!this.active)
|
|
299
|
-
return;
|
|
300
|
-
const handler = using.get(key);
|
|
301
|
-
let notify;
|
|
302
|
-
if (typeof handler == "function") {
|
|
303
|
-
const callback = handler();
|
|
304
|
-
if (callback === true)
|
|
305
|
-
notify = this.onUpdate(key, parent);
|
|
306
|
-
}
|
|
307
|
-
else if (handler === true)
|
|
308
|
-
notify = this.onUpdate(key, parent);
|
|
309
|
-
const getWhy = () => {
|
|
310
|
-
const update = getUpdate(parent.subject);
|
|
311
|
-
const applicable = update.filter(k => using.has(k));
|
|
312
|
-
UPDATE.set(proxy, applicable);
|
|
313
|
-
};
|
|
314
|
-
if (notify) {
|
|
315
|
-
parent.waiting.add(getWhy);
|
|
316
|
-
parent.waiting.add(notify);
|
|
317
|
-
}
|
|
318
|
-
});
|
|
319
|
-
this.commit = () => {
|
|
320
|
-
this.active = true;
|
|
321
|
-
this.dependant.forEach(x => x.commit());
|
|
322
|
-
return this.release;
|
|
323
|
-
};
|
|
324
|
-
this.release = () => {
|
|
325
|
-
this.dependant.forEach(x => x.release());
|
|
326
|
-
release();
|
|
327
|
-
};
|
|
328
|
-
this.add = (key, value) => {
|
|
329
|
-
if (value !== undefined)
|
|
330
|
-
using.set(key, value);
|
|
331
|
-
else if (!using.has(key))
|
|
332
|
-
using.set(key, true);
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const UPDATE = new WeakMap();
|
|
338
|
-
function getUpdate(subject) {
|
|
339
|
-
return UPDATE.get(subject);
|
|
340
|
-
}
|
|
341
|
-
class Controller {
|
|
342
|
-
constructor(subject) {
|
|
343
|
-
this.subject = subject;
|
|
344
|
-
this.frame = new Set();
|
|
345
|
-
this.waiting = new Set();
|
|
346
|
-
this.followers = new Set();
|
|
347
|
-
}
|
|
348
|
-
subscribe(callback) {
|
|
349
|
-
return new Subscriber(this, callback);
|
|
350
|
-
}
|
|
351
|
-
add(key) {
|
|
352
|
-
const { subject, state } = this;
|
|
353
|
-
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
354
|
-
if (typeof value == "function")
|
|
355
|
-
return;
|
|
356
|
-
if (typeof value == "symbol") {
|
|
357
|
-
const instruction = PENDING.get(value);
|
|
358
|
-
if (instruction)
|
|
359
|
-
instruction.call(this, key, this);
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
state.set(key, value);
|
|
363
|
-
defineProperty(subject, key, {
|
|
364
|
-
enumerable: false,
|
|
365
|
-
set: this.ref(key),
|
|
366
|
-
get() {
|
|
367
|
-
const local = this[LOCAL];
|
|
368
|
-
if (local)
|
|
369
|
-
local.add(key);
|
|
370
|
-
return state.get(key);
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
addListener(listener) {
|
|
375
|
-
this.followers.add(listener);
|
|
376
|
-
return () => {
|
|
377
|
-
this.followers.delete(listener);
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
ref(key, handler) {
|
|
381
|
-
const { subject, state } = this;
|
|
382
|
-
return (value) => {
|
|
383
|
-
if (state.get(key) == value)
|
|
384
|
-
return;
|
|
385
|
-
if (handler)
|
|
386
|
-
switch (handler.call(subject, value)) {
|
|
387
|
-
case true:
|
|
388
|
-
this.update(key);
|
|
389
|
-
case false:
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
state.set(key, value);
|
|
393
|
-
this.update(key);
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
update(key) {
|
|
397
|
-
const { followers, frame, subject, waiting } = this;
|
|
398
|
-
if (frame.has(key))
|
|
399
|
-
return;
|
|
400
|
-
else if (!frame.size)
|
|
401
|
-
setTimeout(() => {
|
|
402
|
-
flush(this);
|
|
403
|
-
UPDATE.set(subject, Array.from(frame));
|
|
404
|
-
setTimeout(() => {
|
|
405
|
-
UPDATE.delete(subject);
|
|
406
|
-
}, 0);
|
|
407
|
-
frame.clear();
|
|
408
|
-
for (const notify of waiting)
|
|
409
|
-
try {
|
|
410
|
-
waiting.delete(notify);
|
|
411
|
-
notify();
|
|
412
|
-
}
|
|
413
|
-
catch (err) {
|
|
414
|
-
console.error(err);
|
|
415
|
-
}
|
|
416
|
-
}, 0);
|
|
417
|
-
frame.add(key);
|
|
418
|
-
for (const callback of followers) {
|
|
419
|
-
const event = callback(key, this);
|
|
420
|
-
if (typeof event == "function")
|
|
421
|
-
waiting.add(event);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
clear() {
|
|
425
|
-
const listeners = [...this.followers];
|
|
426
|
-
this.followers.clear();
|
|
427
|
-
listeners.forEach(x => x(null, this));
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
191
|
const Oops$9 = issues({
|
|
432
192
|
Timeout: (keys, timeout) => `No update for [${keys}] within ${timeout}.`,
|
|
433
193
|
StrictUpdate: () => `Strict update() did not find pending updates.`,
|
|
434
194
|
NoChaining: () => `Then called with undefined; update promise will never catch nor supports chaining.`
|
|
435
195
|
});
|
|
436
|
-
const CONTROL = Symbol("CONTROL");
|
|
437
196
|
const WHY = Symbol("UPDATE");
|
|
438
197
|
const LOCAL = Symbol("LOCAL");
|
|
439
198
|
const STATE = Symbol("STATE");
|
|
440
199
|
class Model {
|
|
441
200
|
constructor() {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
201
|
+
defineProperty(this, CONTROL, {
|
|
202
|
+
value: new Controller(this)
|
|
203
|
+
});
|
|
204
|
+
defineProperty(this, "is", {
|
|
205
|
+
value: this
|
|
206
|
+
});
|
|
207
|
+
defineProperty(this, "set", {
|
|
208
|
+
configurable: true,
|
|
209
|
+
get: () => {
|
|
210
|
+
const controller = ensure(this);
|
|
211
|
+
const value = (key, value) => {
|
|
212
|
+
controller.state.set(key, value);
|
|
213
|
+
controller.update(key);
|
|
214
|
+
};
|
|
215
|
+
for (const key of controller.state.keys())
|
|
216
|
+
defineProperty(value, key, {
|
|
217
|
+
value: controller.ref(key)
|
|
218
|
+
});
|
|
219
|
+
defineProperty(this, "set", { value });
|
|
220
|
+
return value;
|
|
221
|
+
}
|
|
454
222
|
});
|
|
455
223
|
}
|
|
456
224
|
get [STATE]() {
|
|
@@ -636,6 +404,183 @@ class Model {
|
|
|
636
404
|
}
|
|
637
405
|
}
|
|
638
406
|
|
|
407
|
+
class Subscriber {
|
|
408
|
+
constructor(parent, onUpdate) {
|
|
409
|
+
this.onUpdate = onUpdate;
|
|
410
|
+
this.active = false;
|
|
411
|
+
this.dependant = new Set();
|
|
412
|
+
const proxy = create(parent.subject);
|
|
413
|
+
const using = new Map();
|
|
414
|
+
const listen = this.add = (key, value) => {
|
|
415
|
+
if (value !== undefined)
|
|
416
|
+
using.set(key, value);
|
|
417
|
+
else if (!using.has(key))
|
|
418
|
+
using.set(key, true);
|
|
419
|
+
};
|
|
420
|
+
LISTEN.set(proxy, listen);
|
|
421
|
+
defineProperty(proxy, LOCAL, { value: this });
|
|
422
|
+
defineProperty(this, "proxy", {
|
|
423
|
+
configurable: true,
|
|
424
|
+
get() {
|
|
425
|
+
if (UPDATE.has(proxy))
|
|
426
|
+
setTimeout(() => UPDATE.delete(proxy), 0);
|
|
427
|
+
return proxy;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
const release = parent.addListener(key => {
|
|
431
|
+
if (!this.active)
|
|
432
|
+
return;
|
|
433
|
+
const handler = using.get(key);
|
|
434
|
+
let notify;
|
|
435
|
+
if (typeof handler == "function") {
|
|
436
|
+
const callback = handler();
|
|
437
|
+
if (callback === true)
|
|
438
|
+
notify = this.onUpdate(key, parent);
|
|
439
|
+
}
|
|
440
|
+
else if (handler === true)
|
|
441
|
+
notify = this.onUpdate(key, parent);
|
|
442
|
+
if (!notify)
|
|
443
|
+
return;
|
|
444
|
+
const notate = () => {
|
|
445
|
+
UPDATE.set(proxy, getUpdate(parent.subject).filter(k => using.has(k)));
|
|
446
|
+
};
|
|
447
|
+
parent.waiting.add(notate);
|
|
448
|
+
parent.waiting.add(notify);
|
|
449
|
+
});
|
|
450
|
+
this.commit = () => {
|
|
451
|
+
this.active = true;
|
|
452
|
+
this.dependant.forEach(x => x.commit());
|
|
453
|
+
return this.release;
|
|
454
|
+
};
|
|
455
|
+
this.release = () => {
|
|
456
|
+
this.dependant.forEach(x => x.release());
|
|
457
|
+
release();
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const UPDATE = new WeakMap();
|
|
463
|
+
const LISTEN = new WeakMap();
|
|
464
|
+
const CONTROL = Symbol("CONTROL");
|
|
465
|
+
function getUpdate(subject) {
|
|
466
|
+
return UPDATE.get(subject);
|
|
467
|
+
}
|
|
468
|
+
class Controller {
|
|
469
|
+
constructor(subject) {
|
|
470
|
+
this.subject = subject;
|
|
471
|
+
this.frame = new Set();
|
|
472
|
+
this.waiting = new Set();
|
|
473
|
+
this.followers = new Set();
|
|
474
|
+
}
|
|
475
|
+
subscribe(callback) {
|
|
476
|
+
return new Subscriber(this, callback);
|
|
477
|
+
}
|
|
478
|
+
add(key) {
|
|
479
|
+
const { subject, state } = this;
|
|
480
|
+
const { value } = getOwnPropertyDescriptor(subject, key);
|
|
481
|
+
if (typeof value == "function")
|
|
482
|
+
return;
|
|
483
|
+
if (typeof value == "symbol") {
|
|
484
|
+
const instruction = PENDING.get(value);
|
|
485
|
+
if (instruction)
|
|
486
|
+
instruction.call(this, key, this);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
state.set(key, value);
|
|
490
|
+
defineProperty(subject, key, {
|
|
491
|
+
enumerable: false,
|
|
492
|
+
set: this.ref(key),
|
|
493
|
+
get() {
|
|
494
|
+
const listen = LISTEN.get(this);
|
|
495
|
+
if (listen)
|
|
496
|
+
listen(key);
|
|
497
|
+
return state.get(key);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
addListener(listener) {
|
|
502
|
+
this.followers.add(listener);
|
|
503
|
+
return () => {
|
|
504
|
+
this.followers.delete(listener);
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
ref(key, handler) {
|
|
508
|
+
const { subject, state } = this;
|
|
509
|
+
return (value) => {
|
|
510
|
+
if (state.get(key) == value)
|
|
511
|
+
return;
|
|
512
|
+
if (handler)
|
|
513
|
+
switch (handler.call(subject, value)) {
|
|
514
|
+
case true:
|
|
515
|
+
this.update(key);
|
|
516
|
+
case false:
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
state.set(key, value);
|
|
520
|
+
this.update(key);
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
update(key) {
|
|
524
|
+
const { followers, frame, subject, waiting } = this;
|
|
525
|
+
if (frame.has(key))
|
|
526
|
+
return;
|
|
527
|
+
else if (!frame.size)
|
|
528
|
+
setTimeout(() => {
|
|
529
|
+
flush(this);
|
|
530
|
+
UPDATE.set(subject, Array.from(frame));
|
|
531
|
+
setTimeout(() => {
|
|
532
|
+
UPDATE.delete(subject);
|
|
533
|
+
}, 0);
|
|
534
|
+
frame.clear();
|
|
535
|
+
for (const notify of waiting)
|
|
536
|
+
try {
|
|
537
|
+
waiting.delete(notify);
|
|
538
|
+
notify();
|
|
539
|
+
}
|
|
540
|
+
catch (err) {
|
|
541
|
+
console.error(err);
|
|
542
|
+
}
|
|
543
|
+
}, 0);
|
|
544
|
+
frame.add(key);
|
|
545
|
+
for (const callback of followers) {
|
|
546
|
+
const event = callback(key, this);
|
|
547
|
+
if (typeof event == "function")
|
|
548
|
+
waiting.add(event);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
clear() {
|
|
552
|
+
const listeners = [...this.followers];
|
|
553
|
+
this.followers.clear();
|
|
554
|
+
listeners.forEach(x => x(null, this));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
function ensure(subject, cb) {
|
|
558
|
+
let control = subject[CONTROL];
|
|
559
|
+
if (!control)
|
|
560
|
+
defineProperty(subject, CONTROL, {
|
|
561
|
+
value: control =
|
|
562
|
+
new Controller(subject)
|
|
563
|
+
});
|
|
564
|
+
if (!control.state) {
|
|
565
|
+
const { waiting } = control;
|
|
566
|
+
if (cb) {
|
|
567
|
+
let done;
|
|
568
|
+
waiting.add(() => {
|
|
569
|
+
done = cb(control);
|
|
570
|
+
});
|
|
571
|
+
return () => done && done();
|
|
572
|
+
}
|
|
573
|
+
control.state = new Map();
|
|
574
|
+
for (const key in subject)
|
|
575
|
+
control.add(key);
|
|
576
|
+
const callback = Array.from(waiting);
|
|
577
|
+
waiting.clear();
|
|
578
|
+
for (const cb of callback)
|
|
579
|
+
cb();
|
|
580
|
+
}
|
|
581
|
+
return cb ? cb(control) : control;
|
|
582
|
+
}
|
|
583
|
+
|
|
639
584
|
const PENDING = new Map();
|
|
640
585
|
function apply(fn, label) {
|
|
641
586
|
const name = label || fn.name || "pending";
|
|
@@ -654,11 +599,11 @@ function apply(fn, label) {
|
|
|
654
599
|
defineProperty(subject, key, output);
|
|
655
600
|
return false;
|
|
656
601
|
}
|
|
602
|
+
let { get: onGet, set: onSet, suspense } = output;
|
|
603
|
+
if ("value" in output)
|
|
604
|
+
state.set(key, output.value);
|
|
657
605
|
if ("recursive" in output && output.recursive)
|
|
658
|
-
|
|
659
|
-
const desc = output;
|
|
660
|
-
if ("value" in desc)
|
|
661
|
-
state.set(key, desc.value);
|
|
606
|
+
onGet = getRecursive(key, this);
|
|
662
607
|
if ("destroy" in output) {
|
|
663
608
|
const { destroy } = output;
|
|
664
609
|
if (destroy)
|
|
@@ -667,57 +612,85 @@ function apply(fn, label) {
|
|
|
667
612
|
destroy();
|
|
668
613
|
});
|
|
669
614
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
local
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
615
|
+
defineProperty(subject, key, {
|
|
616
|
+
enumerable: output.enumerable,
|
|
617
|
+
set: onSet !== false
|
|
618
|
+
? this.ref(key, onSet)
|
|
619
|
+
: undefined,
|
|
620
|
+
get() {
|
|
621
|
+
if (!state.has(key) && suspense)
|
|
622
|
+
throw suspend(control, key);
|
|
623
|
+
const listen = LISTEN.get(this);
|
|
624
|
+
const local = this[LOCAL];
|
|
625
|
+
if (listen)
|
|
626
|
+
listen(key);
|
|
627
|
+
return onGet
|
|
628
|
+
? onGet(local)
|
|
629
|
+
: state.get(key);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
685
632
|
}
|
|
686
633
|
PENDING.set(placeholder, setup);
|
|
687
634
|
return placeholder;
|
|
688
635
|
}
|
|
689
636
|
function getRecursive(key, from) {
|
|
690
637
|
const context = new WeakMap();
|
|
691
|
-
const { state } = from;
|
|
692
638
|
return (local) => {
|
|
693
639
|
if (!local)
|
|
694
|
-
return state.get(key);
|
|
640
|
+
return from.state.get(key);
|
|
695
641
|
if (!context.has(local)) {
|
|
696
|
-
let
|
|
642
|
+
let reset;
|
|
697
643
|
const init = () => {
|
|
698
|
-
if (
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
context.set(local, undefined);
|
|
702
|
-
child = undefined;
|
|
703
|
-
}
|
|
704
|
-
const value = state.get(key);
|
|
644
|
+
if (reset)
|
|
645
|
+
reset();
|
|
646
|
+
const value = from.state.get(key);
|
|
705
647
|
if (value && CONTROL in value) {
|
|
706
|
-
child = ensure(value).subscribe(local.onUpdate);
|
|
648
|
+
const child = ensure(value).subscribe(local.onUpdate);
|
|
707
649
|
if (local.active)
|
|
708
650
|
child.commit();
|
|
709
651
|
local.dependant.add(child);
|
|
710
652
|
context.set(local, child.proxy);
|
|
653
|
+
reset = () => {
|
|
654
|
+
child.release();
|
|
655
|
+
local.dependant.delete(child);
|
|
656
|
+
context.set(local, undefined);
|
|
657
|
+
reset = undefined;
|
|
658
|
+
};
|
|
711
659
|
}
|
|
712
660
|
return true;
|
|
713
661
|
};
|
|
714
|
-
init();
|
|
715
662
|
local.add(key, init);
|
|
663
|
+
init();
|
|
716
664
|
}
|
|
717
665
|
return context.get(local);
|
|
718
666
|
};
|
|
719
667
|
}
|
|
720
668
|
|
|
669
|
+
/*! *****************************************************************************
|
|
670
|
+
Copyright (c) Microsoft Corporation.
|
|
671
|
+
|
|
672
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
673
|
+
purpose with or without fee is hereby granted.
|
|
674
|
+
|
|
675
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
676
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
677
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
678
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
679
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
680
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
681
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
682
|
+
***************************************************************************** */
|
|
683
|
+
|
|
684
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
685
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
686
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
687
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
688
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
689
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
690
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
|
|
721
694
|
const Oops$8 = issues({
|
|
722
695
|
DuplicatePending: (key) => `Invoked action ${key} but one is already active.`
|
|
723
696
|
});
|
|
@@ -748,161 +721,115 @@ function act(task) {
|
|
|
748
721
|
});
|
|
749
722
|
}
|
|
750
723
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const end = super.push(...items);
|
|
768
|
-
this.update(0, end);
|
|
769
|
-
return end;
|
|
770
|
-
}
|
|
771
|
-
splice(start, deleteCount, ...rest) {
|
|
772
|
-
const end = deleteCount !== rest.length ? Infinity : deleteCount;
|
|
773
|
-
this.update(start, end);
|
|
774
|
-
return super.splice(start, deleteCount, ...rest);
|
|
724
|
+
function factoryMode(self, output, key, required) {
|
|
725
|
+
const { subject, state } = self;
|
|
726
|
+
let pending;
|
|
727
|
+
let error;
|
|
728
|
+
if (output instanceof Promise) {
|
|
729
|
+
state.set(key, undefined);
|
|
730
|
+
pending = output
|
|
731
|
+
.catch(err => error = err)
|
|
732
|
+
.then(val => {
|
|
733
|
+
state.set(key, val);
|
|
734
|
+
return val;
|
|
735
|
+
})
|
|
736
|
+
.finally(() => {
|
|
737
|
+
pending = undefined;
|
|
738
|
+
self.update(key);
|
|
739
|
+
});
|
|
775
740
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
let rangeB = 0;
|
|
785
|
-
const onUpdate = () => {
|
|
786
|
-
const [lastA, lastB] = array.lastUpdate;
|
|
787
|
-
if (rangeA <= lastB && rangeB >= lastA)
|
|
788
|
-
return true;
|
|
789
|
-
};
|
|
790
|
-
const listen = (eventA, eventB) => {
|
|
791
|
-
if (context.active)
|
|
792
|
-
return;
|
|
793
|
-
context.add(key, onUpdate);
|
|
794
|
-
rangeA = Math.min(rangeA, eventA);
|
|
795
|
-
rangeB = Math.max(rangeB, eventB);
|
|
796
|
-
};
|
|
797
|
-
proxy[Symbol.iterator] = () => {
|
|
798
|
-
listen(0, Infinity);
|
|
799
|
-
return array[Symbol.iterator]();
|
|
800
|
-
};
|
|
801
|
-
return proxy;
|
|
802
|
-
};
|
|
803
|
-
return {
|
|
804
|
-
value: array,
|
|
805
|
-
set: false,
|
|
806
|
-
get: (local) => {
|
|
807
|
-
if (!local)
|
|
808
|
-
return this.state.get(key);
|
|
809
|
-
if (context.has(local))
|
|
810
|
-
return context.get(local);
|
|
811
|
-
const output = getLocal(local);
|
|
812
|
-
context.set(local, output);
|
|
813
|
-
return output;
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
|
-
});
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
function ref(callback) {
|
|
820
|
-
return apply(function ref(key) {
|
|
821
|
-
const value = this.ref(key, callback && createValueEffect(callback));
|
|
822
|
-
defineProperty(value, "current", {
|
|
823
|
-
set: value,
|
|
824
|
-
get: () => this.state.get(key)
|
|
741
|
+
state.set(key, output);
|
|
742
|
+
const suspend = () => {
|
|
743
|
+
if (required === false)
|
|
744
|
+
return undefined;
|
|
745
|
+
const issue = Oops$7.NotReady(subject, key);
|
|
746
|
+
Object.assign(pending, {
|
|
747
|
+
message: issue.message,
|
|
748
|
+
stack: issue.stack
|
|
825
749
|
});
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
750
|
+
throw pending;
|
|
751
|
+
};
|
|
752
|
+
return () => {
|
|
753
|
+
if (error)
|
|
754
|
+
throw error;
|
|
755
|
+
if (pending)
|
|
756
|
+
return suspend();
|
|
757
|
+
if (state.has(key))
|
|
758
|
+
return state.get(key);
|
|
759
|
+
};
|
|
831
760
|
}
|
|
832
761
|
|
|
833
762
|
const Oops$7 = issues({
|
|
834
|
-
|
|
763
|
+
BadSource: (model, property, got) => `Bad from-instruction provided to ${model}.${property}. Expects an arrow-function or a Model as source. Got ${got}.`,
|
|
764
|
+
PeerNotAllowed: (model, property) => `Attempted to use an instruction result (probably use or tap) as computed source for ${model}.${property}. This is not possible.`,
|
|
765
|
+
ComputeFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
835
766
|
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`,
|
|
836
|
-
|
|
767
|
+
FactoryFailed: (model, key) => `Generating initial value for ${model}.${key} failed.`,
|
|
768
|
+
Failed: (parent, property, initial) => `An exception was thrown while ${initial ? "initializing" : "refreshing"} [${parent}.${property}].`
|
|
837
769
|
});
|
|
838
|
-
function
|
|
839
|
-
return apply(function
|
|
840
|
-
const { subject
|
|
841
|
-
const
|
|
842
|
-
|
|
843
|
-
let
|
|
844
|
-
|
|
845
|
-
|
|
770
|
+
function get(arg0, arg1, arg2) {
|
|
771
|
+
return apply(function get(key) {
|
|
772
|
+
const { subject } = this;
|
|
773
|
+
const computeRequired = arg1 === true || arg2 === true;
|
|
774
|
+
const factoryRequired = arg1 !== false && arg2 !== false;
|
|
775
|
+
let getter;
|
|
776
|
+
// Easy mistake, using a peer, will always be unresolved.
|
|
777
|
+
if (typeof arg0 == "symbol")
|
|
778
|
+
throw Oops$7.PeerNotAllowed(subject, key);
|
|
779
|
+
if (typeof arg0 == "function" && /^[A-Z]/.test(arg0.name))
|
|
780
|
+
throw Oops$7.BadSource(subject, key, arg0);
|
|
781
|
+
this.state.set(key, undefined);
|
|
846
782
|
const init = () => {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
return
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
});
|
|
783
|
+
let source = this;
|
|
784
|
+
let setter;
|
|
785
|
+
if (typeof arg0 == "function") {
|
|
786
|
+
const result = mayRetry(() => arg0.call(subject, key, subject));
|
|
787
|
+
if (typeof result == "function")
|
|
788
|
+
setter = result;
|
|
789
|
+
else {
|
|
790
|
+
getter = factoryMode(this, result, key, factoryRequired);
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
else if (arg0 instanceof Promise) {
|
|
795
|
+
getter = factoryMode(this, arg0, key, factoryRequired);
|
|
861
796
|
return;
|
|
862
797
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
message: issue.message,
|
|
872
|
-
stack: issue.stack
|
|
873
|
-
});
|
|
874
|
-
throw pending;
|
|
798
|
+
else if (typeof arg1 == "function") {
|
|
799
|
+
// replace source controller in-case it is different
|
|
800
|
+
source = ensure(arg0);
|
|
801
|
+
setter = arg1;
|
|
802
|
+
}
|
|
803
|
+
else
|
|
804
|
+
throw new Error(`Factory argument cannot be ${arg1}`);
|
|
805
|
+
getter = computeMode(this, source, setter, key, computeRequired);
|
|
875
806
|
};
|
|
876
|
-
if (
|
|
807
|
+
if (typeof arg0 == "function" && factoryRequired)
|
|
877
808
|
try {
|
|
878
809
|
init();
|
|
879
810
|
}
|
|
880
811
|
catch (err) {
|
|
881
|
-
Oops$7.
|
|
812
|
+
Oops$7.ComputeFailed(subject, key).warn();
|
|
882
813
|
throw err;
|
|
883
814
|
}
|
|
884
|
-
|
|
885
|
-
if (
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
throw error;
|
|
889
|
-
if (state.has(key))
|
|
890
|
-
return state.get(key);
|
|
891
|
-
let output = init();
|
|
892
|
-
return pending
|
|
893
|
-
? suspend()
|
|
894
|
-
: output;
|
|
815
|
+
return () => {
|
|
816
|
+
if (!getter)
|
|
817
|
+
init();
|
|
818
|
+
return getter();
|
|
895
819
|
};
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function ref(callback) {
|
|
824
|
+
return apply(function ref(key) {
|
|
825
|
+
const value = this.ref(key, callback && createValueEffect(callback));
|
|
826
|
+
defineProperty(value, "current", {
|
|
827
|
+
set: value,
|
|
828
|
+
get: () => this.state.get(key)
|
|
829
|
+
});
|
|
903
830
|
return {
|
|
904
|
-
|
|
905
|
-
|
|
831
|
+
value,
|
|
832
|
+
explicit: true
|
|
906
833
|
};
|
|
907
834
|
});
|
|
908
835
|
}
|
|
@@ -924,106 +851,25 @@ function set(value, argument) {
|
|
|
924
851
|
});
|
|
925
852
|
}
|
|
926
853
|
|
|
927
|
-
const Parent = new WeakMap();
|
|
928
|
-
const Oops$6 = issues({
|
|
929
|
-
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
930
|
-
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
931
|
-
});
|
|
932
|
-
function parent(Expects, required) {
|
|
933
|
-
return apply(function parent() {
|
|
934
|
-
const child = this.subject;
|
|
935
|
-
const value = Parent.get(child);
|
|
936
|
-
const expected = Expects.name;
|
|
937
|
-
if (!value) {
|
|
938
|
-
if (required !== false)
|
|
939
|
-
throw Oops$6.Required(expected, child);
|
|
940
|
-
}
|
|
941
|
-
else if (!(value instanceof Expects))
|
|
942
|
-
throw Oops$6.Unexpected(expected, child, value);
|
|
943
|
-
return { value };
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
|
|
947
854
|
const ANY = Symbol("any");
|
|
948
855
|
function keyed(control, property, initial) {
|
|
856
|
+
const init = createProxy(emit, watch);
|
|
857
|
+
const frozen = new Set();
|
|
949
858
|
const context = new Map();
|
|
950
859
|
const users = new Map();
|
|
951
860
|
const watched = new WeakMap();
|
|
952
861
|
const update = new Set();
|
|
953
|
-
|
|
954
|
-
let managed;
|
|
955
|
-
manage(initial);
|
|
956
|
-
function reset() {
|
|
957
|
-
frozen.clear();
|
|
958
|
-
}
|
|
862
|
+
let managed = init(initial);
|
|
959
863
|
function watch(on, key) {
|
|
960
864
|
const include = watched.get(on);
|
|
961
865
|
if (include)
|
|
962
866
|
include.add(key);
|
|
963
867
|
}
|
|
964
868
|
function emit(key) {
|
|
965
|
-
control.waiting.add(reset);
|
|
966
869
|
control.update(property);
|
|
870
|
+
control.waiting.add(() => frozen.clear());
|
|
967
871
|
update.forEach(notify => notify(key));
|
|
968
872
|
}
|
|
969
|
-
function manage(current) {
|
|
970
|
-
managed = create(current);
|
|
971
|
-
context.clear();
|
|
972
|
-
assign(managed, {
|
|
973
|
-
delete(key) {
|
|
974
|
-
emit(key);
|
|
975
|
-
return current.delete(key);
|
|
976
|
-
},
|
|
977
|
-
clear() {
|
|
978
|
-
emit(ANY);
|
|
979
|
-
current.clear();
|
|
980
|
-
},
|
|
981
|
-
has(key) {
|
|
982
|
-
watch(this, key);
|
|
983
|
-
return current.has(key);
|
|
984
|
-
},
|
|
985
|
-
keys() {
|
|
986
|
-
watch(this, ANY);
|
|
987
|
-
return current.keys();
|
|
988
|
-
},
|
|
989
|
-
values() {
|
|
990
|
-
watch(this, ANY);
|
|
991
|
-
return current.values();
|
|
992
|
-
},
|
|
993
|
-
entries() {
|
|
994
|
-
watch(this, ANY);
|
|
995
|
-
return current.entries();
|
|
996
|
-
},
|
|
997
|
-
[Symbol.iterator]() {
|
|
998
|
-
watch(this, ANY);
|
|
999
|
-
return current[Symbol.iterator]();
|
|
1000
|
-
},
|
|
1001
|
-
}, current instanceof Set
|
|
1002
|
-
? {
|
|
1003
|
-
add(key) {
|
|
1004
|
-
current.add(key);
|
|
1005
|
-
emit(key);
|
|
1006
|
-
return this;
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
: {
|
|
1010
|
-
get(key) {
|
|
1011
|
-
watch(this, ANY);
|
|
1012
|
-
return current.get(key);
|
|
1013
|
-
},
|
|
1014
|
-
set(key, value) {
|
|
1015
|
-
current.set(key, value);
|
|
1016
|
-
emit(key);
|
|
1017
|
-
return this;
|
|
1018
|
-
}
|
|
1019
|
-
});
|
|
1020
|
-
defineProperty(managed, "size", {
|
|
1021
|
-
get() {
|
|
1022
|
-
watch(this, ANY);
|
|
1023
|
-
return current.size;
|
|
1024
|
-
}
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
873
|
function subscribe(local) {
|
|
1028
874
|
const proxy = create(managed);
|
|
1029
875
|
let watch = users.get(local);
|
|
@@ -1066,46 +912,185 @@ function keyed(control, property, initial) {
|
|
|
1066
912
|
},
|
|
1067
913
|
set(next) {
|
|
1068
914
|
control.state.set(property, next);
|
|
1069
|
-
|
|
915
|
+
managed = init(next);
|
|
916
|
+
context.clear();
|
|
1070
917
|
emit(ANY);
|
|
1071
918
|
},
|
|
1072
919
|
destroy() {
|
|
1073
920
|
update.clear();
|
|
921
|
+
context.clear();
|
|
1074
922
|
}
|
|
1075
923
|
};
|
|
924
|
+
}
|
|
925
|
+
function createProxy(emit, watch) {
|
|
926
|
+
return (from) => {
|
|
927
|
+
const proxy = create(from);
|
|
928
|
+
assign(proxy, {
|
|
929
|
+
from,
|
|
930
|
+
delete(key) {
|
|
931
|
+
emit(key);
|
|
932
|
+
return from.delete(key);
|
|
933
|
+
},
|
|
934
|
+
clear() {
|
|
935
|
+
emit(ANY);
|
|
936
|
+
from.clear();
|
|
937
|
+
},
|
|
938
|
+
has(key) {
|
|
939
|
+
watch(this, key);
|
|
940
|
+
return from.has(key);
|
|
941
|
+
},
|
|
942
|
+
keys() {
|
|
943
|
+
watch(this, ANY);
|
|
944
|
+
return from.keys();
|
|
945
|
+
},
|
|
946
|
+
values() {
|
|
947
|
+
watch(this, ANY);
|
|
948
|
+
return from.values();
|
|
949
|
+
},
|
|
950
|
+
entries() {
|
|
951
|
+
watch(this, ANY);
|
|
952
|
+
return from.entries();
|
|
953
|
+
},
|
|
954
|
+
forEach(callbackfn, thisArg) {
|
|
955
|
+
const acc = [];
|
|
956
|
+
from.forEach((a, b, c) => {
|
|
957
|
+
const result = callbackfn.call(thisArg, a, b, c);
|
|
958
|
+
if (result !== undefined)
|
|
959
|
+
acc.push(result);
|
|
960
|
+
});
|
|
961
|
+
watch(this, ANY);
|
|
962
|
+
return acc;
|
|
963
|
+
},
|
|
964
|
+
[Symbol.iterator]() {
|
|
965
|
+
watch(this, ANY);
|
|
966
|
+
return from[Symbol.iterator]();
|
|
967
|
+
},
|
|
968
|
+
}, from instanceof Set
|
|
969
|
+
? {
|
|
970
|
+
add(key) {
|
|
971
|
+
from.add(key);
|
|
972
|
+
emit(key);
|
|
973
|
+
return this;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
: {
|
|
977
|
+
get(key) {
|
|
978
|
+
watch(this, ANY);
|
|
979
|
+
return from.get(key);
|
|
980
|
+
},
|
|
981
|
+
set(key, value) {
|
|
982
|
+
from.set(key, value);
|
|
983
|
+
emit(key);
|
|
984
|
+
return this;
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
defineProperty(proxy, "size", {
|
|
988
|
+
get() {
|
|
989
|
+
watch(this, ANY);
|
|
990
|
+
return from.size;
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
return proxy;
|
|
994
|
+
};
|
|
1076
995
|
}
|
|
1077
996
|
|
|
1078
|
-
const
|
|
997
|
+
const Parent = new WeakMap();
|
|
998
|
+
const Oops$6 = issues({
|
|
1079
999
|
BadArgument: (type) => `Instruction \`use\` cannot accept argument type of ${type}.`,
|
|
1000
|
+
NotReady: (model, key) => `Value ${model}.${key} value is not yet available.`
|
|
1080
1001
|
});
|
|
1081
1002
|
function use$1(input, argument) {
|
|
1082
1003
|
return apply(function use(key) {
|
|
1083
1004
|
const { state, subject } = this;
|
|
1005
|
+
const required = argument !== false;
|
|
1006
|
+
let pending;
|
|
1007
|
+
let error;
|
|
1008
|
+
let get = (_local) => state.get(key);
|
|
1084
1009
|
if (typeof input === "function")
|
|
1085
|
-
input =
|
|
1010
|
+
input = /^[A-Z]/.test(input.name)
|
|
1011
|
+
? new input() : input;
|
|
1086
1012
|
else if (input && typeof input !== "object")
|
|
1087
|
-
throw Oops$
|
|
1013
|
+
throw Oops$6.BadArgument(typeof input);
|
|
1088
1014
|
if (input instanceof Map || input instanceof Set)
|
|
1089
1015
|
return keyed(this, key, input);
|
|
1090
|
-
|
|
1016
|
+
const onUpdate = (next) => {
|
|
1091
1017
|
state.set(key, next);
|
|
1092
1018
|
if (next) {
|
|
1019
|
+
get = getRecursive(key, this);
|
|
1093
1020
|
Parent.set(next, subject);
|
|
1094
1021
|
ensure(next);
|
|
1095
1022
|
}
|
|
1096
1023
|
if (typeof argument == "function")
|
|
1097
1024
|
argument(next);
|
|
1098
1025
|
return true;
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1026
|
+
};
|
|
1027
|
+
const suspend = () => {
|
|
1028
|
+
if (required === false)
|
|
1029
|
+
return;
|
|
1030
|
+
const issue = Oops$6.NotReady(subject, key);
|
|
1031
|
+
Object.assign(pending, {
|
|
1032
|
+
message: issue.message,
|
|
1033
|
+
stack: issue.stack
|
|
1034
|
+
});
|
|
1035
|
+
throw pending;
|
|
1036
|
+
};
|
|
1037
|
+
const initialize = () => {
|
|
1038
|
+
const output = typeof input == "function" ?
|
|
1039
|
+
mayRetry(() => input.call(subject, subject)) :
|
|
1040
|
+
input;
|
|
1041
|
+
if (output instanceof Promise) {
|
|
1042
|
+
pending = output
|
|
1043
|
+
.catch(err => error = err)
|
|
1044
|
+
.then(val => {
|
|
1045
|
+
onUpdate(val);
|
|
1046
|
+
return val;
|
|
1047
|
+
})
|
|
1048
|
+
.finally(() => {
|
|
1049
|
+
pending = undefined;
|
|
1050
|
+
this.update(key);
|
|
1051
|
+
});
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
onUpdate(output);
|
|
1055
|
+
};
|
|
1056
|
+
if (input !== undefined && required)
|
|
1057
|
+
initialize();
|
|
1102
1058
|
return {
|
|
1103
1059
|
set: onUpdate,
|
|
1104
|
-
|
|
1060
|
+
get(local) {
|
|
1061
|
+
if (pending)
|
|
1062
|
+
return suspend();
|
|
1063
|
+
if (error)
|
|
1064
|
+
throw error;
|
|
1065
|
+
if (!state.has(key))
|
|
1066
|
+
initialize();
|
|
1067
|
+
if (pending)
|
|
1068
|
+
return suspend();
|
|
1069
|
+
return get(local);
|
|
1070
|
+
}
|
|
1105
1071
|
};
|
|
1106
1072
|
});
|
|
1107
1073
|
}
|
|
1108
1074
|
|
|
1075
|
+
const Oops$5 = issues({
|
|
1076
|
+
Required: (expects, child) => `New ${child} created standalone but requires parent of type ${expects}. Did you remember to create via use(${child})?`,
|
|
1077
|
+
Unexpected: (expects, child, got) => `New ${child} created as child of ${got}, but must be instanceof ${expects}.`,
|
|
1078
|
+
});
|
|
1079
|
+
function has(Expects, required) {
|
|
1080
|
+
return apply(function parent() {
|
|
1081
|
+
const child = this.subject;
|
|
1082
|
+
const value = Parent.get(child);
|
|
1083
|
+
const expected = Expects.name;
|
|
1084
|
+
if (!value) {
|
|
1085
|
+
if (required !== false)
|
|
1086
|
+
throw Oops$5.Required(expected, child);
|
|
1087
|
+
}
|
|
1088
|
+
else if (!(value instanceof Expects))
|
|
1089
|
+
throw Oops$5.Unexpected(expected, child, value);
|
|
1090
|
+
return { value };
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1109
1094
|
class Lookup {
|
|
1110
1095
|
constructor() {
|
|
1111
1096
|
this.table = new Map();
|
|
@@ -1390,12 +1375,12 @@ class MVC extends Model {
|
|
|
1390
1375
|
});
|
|
1391
1376
|
return instance;
|
|
1392
1377
|
}, []);
|
|
1393
|
-
usePeerContext(instance.
|
|
1378
|
+
usePeerContext(instance.is);
|
|
1394
1379
|
return instance;
|
|
1395
1380
|
}
|
|
1396
1381
|
static use(a, b) {
|
|
1397
1382
|
const instance = useModel(this, a, b);
|
|
1398
|
-
usePeerContext(instance.
|
|
1383
|
+
usePeerContext(instance.is);
|
|
1399
1384
|
return instance;
|
|
1400
1385
|
}
|
|
1401
1386
|
/**
|
|
@@ -1539,12 +1524,9 @@ exports.STATE = STATE;
|
|
|
1539
1524
|
exports.WHY = WHY;
|
|
1540
1525
|
exports.act = act;
|
|
1541
1526
|
exports.apply = apply;
|
|
1542
|
-
exports.array = array;
|
|
1543
1527
|
exports["default"] = MVC;
|
|
1544
|
-
exports.from = get;
|
|
1545
1528
|
exports.get = get;
|
|
1546
|
-
exports.
|
|
1547
|
-
exports.put = put;
|
|
1529
|
+
exports.has = has;
|
|
1548
1530
|
exports.ref = ref;
|
|
1549
1531
|
exports.set = set;
|
|
1550
1532
|
exports.tap = tap;
|