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