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